ENTAXY-374 release 1.8.2

This commit is contained in:
2022-08-23 13:40:11 +03:00
parent b68642f81c
commit 1061b96c7e
616 changed files with 60896 additions and 3202 deletions

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producer-api</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: PRODUCER API</name>
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: PRODUCER API</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.core.producer.api</bundle.osgi.export.pkg>
</properties>
</project>

View File

@ -0,0 +1,46 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.List;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public interface EntaxyProducer {
public interface EntaxyProducerListener {
public void factoryAdded(String factoryId, String factoryType, EntaxyProducer producer);
public void factoryRemoved(String factoryId, String factoryType, EntaxyProducer producer);
}
public void addListener(EntaxyProducerListener listener);
public void removeListener(EntaxyProducerListener listener);
public String getProducerId();
public List<String> getSupportedTypes();
public List<EntaxyFactory> getAllFactories();
public List<EntaxyFactory> getFactoriesForType(String factoryType);
public EntaxyFactory getFactoryById(String factoryId);
}

View File

@ -0,0 +1,58 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.List;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public interface EntaxyProducerService {
public static interface INSTRUCTIONS {
public static final String PRINT_OUTPUT = "printOutput";
public static final String SKIP = "skip";
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);
public List<ProducingCommandExecutor> getAvailableCommands();
public void registerCommand(ProducingCommandExecutor commandExecutor);
public ProducingCommandExecutor getCommandById(String id);
}

View File

@ -0,0 +1,89 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-api
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class EntaxyProducerUtils {
protected static Gson sharedGson = new Gson();
protected static class InstructionsItemBuilder {
protected JsonObject instructionsJson;
protected InstructionsItemBuilder(JsonObject jsonObject) {
this.instructionsJson = jsonObject;
}
}
public static class InstructionsBuilder extends InstructionsItemBuilder {
protected InstructionsBuilder(JsonObject jsonObject) {
super(jsonObject);
}
public CommandBuilder command(String commandName) {
if (!instructionsJson.has(commandName))
instructionsJson.add(commandName, new JsonObject());
return new CommandBuilder(instructionsJson, instructionsJson.get(commandName).getAsJsonObject());
}
public CommandBuilder any() {
return 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 InstructionsBuilder instructions() {
return instructions(new JsonObject());
}
public static InstructionsBuilder instructions(JsonObject jsonObject) {
return new InstructionsBuilder(jsonObject);
}
}

View File

@ -0,0 +1,28 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public interface EntaxyWrappedFactory extends EntaxyFactory {
public EntaxyFactory getOrigin();
}

View File

@ -0,0 +1,172 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate.OPERATIONS;
public class ExecutionPlan implements Iterable<ExecutionTask> {
public List<ExecutionTask> tasks = new ArrayList<>();
public ExecutionPlan(List<ExecutionTask> tasks) {
this.tasks = tasks;
}
protected Iterator<ExecutionTask> currentIterator;
protected ExecutionPlanIterator iterator = null;
@Override
public Iterator<ExecutionTask> iterator() {
this.currentIterator = this.tasks.listIterator();
if (this.iterator == null)
this.iterator = new ExecutionPlanIterator();
return this.iterator;
}
public List<ExecutionPlanUpdate.OPERATIONS> applyUpdate(ExecutionPlanUpdate planUpdate) throws Exception {
List<ExecutionPlanUpdate.OPERATIONS> result = new LinkedList<>();
for (ExecutionPlanUpdate.ExecutionPlanUpdateRecord record: planUpdate.records) {
if (ExecutionPlanUpdate.OPERATIONS.RESET.equals(record.operation)) {
String target = record.target;
reset(target);
result.add(OPERATIONS.RESET);
continue;
}
if (ExecutionPlanUpdate.OPERATIONS.UPDATE_INSTRUCTIONS.equals(record.operation)) {
String target = record.target;
synchronized (tasks) {
for (ExecutionTask task: tasks)
if (task.commandId.equals(target)) {
if ((task.instructions == null) || task.instructions.isEmpty())
task.instructions = new HashMap<>();
task.instructions.putAll(record.values);
result.add(OPERATIONS.UPDATE_INSTRUCTIONS);
continue;
}
}
}
}
return result;
}
protected void reset(String commandId) throws Exception {
synchronized (tasks) {
if (CommonUtils.isValid(commandId)) {
for (int i=0; i<tasks.size(); i++)
if (tasks.get(i).commandId.equals(commandId)) {
this.currentIterator = tasks.listIterator(i);
return;
}
} else {
this.currentIterator = tasks.listIterator();
}
}
}
protected Iterator<ExecutionTask> getCurrentIterator(){
return this.currentIterator;
}
protected class ExecutionPlanIterator implements Iterator<ExecutionTask>{
@Override
public boolean hasNext() {
return ExecutionPlan.this.getCurrentIterator().hasNext();
}
@Override
public ExecutionTask next() {
return ExecutionPlan.this.getCurrentIterator().next();
}
}
public static class ExecutionPlanUpdate {
public static enum OPERATIONS {
RESET,
UPDATE_INSTRUCTIONS
}
protected List<ExecutionPlanUpdateRecord> records = new LinkedList<>();
public static class ExecutionPlanUpdateRecord {
protected ExecutionPlanUpdate planUpdate;
protected OPERATIONS operation;
protected String target;
protected Map<String, Object> values = new LinkedHashMap<>();
protected ExecutionPlanUpdateRecord(ExecutionPlanUpdate planUpdate) {
this.planUpdate = planUpdate;
}
public ExecutionPlanUpdateRecord target(String value) {
this.target = value;
return this;
}
public ExecutionPlanUpdateRecord value(String name, Object value) {
this.values.put(name, value);
return this;
}
public ExecutionPlanUpdate complete() {
return this.planUpdate;
}
}
public static ExecutionPlanUpdate create() {
return new ExecutionPlanUpdate();
}
public ExecutionPlanUpdateRecord reset() {
ExecutionPlanUpdateRecord record = new ExecutionPlanUpdateRecord(this);
record.operation = OPERATIONS.RESET;
this.records.add(record);
return record;
}
public ExecutionPlanUpdateRecord updateInstructions() {
ExecutionPlanUpdateRecord record = new ExecutionPlanUpdateRecord(this);
record.operation = OPERATIONS.UPDATE_INSTRUCTIONS;
this.records.add(record);
return record;
}
}
}

View File

@ -0,0 +1,42 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExecutionTask {
public String commandId;
public ProducingCommandExecutor executor;
public Map<String, Object> instructions = new HashMap<>();
public List<ExecutionTask> dependsOn = new ArrayList<>();
public ExecutionTask() {
super();
}
public ExecutionTask(String id) {
super();
this.commandId = id;
}
}

View File

@ -0,0 +1,124 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate;
public class ProducerResult {
private static final Logger log = LoggerFactory.getLogger(ProducerResult.class);
public static class CommandResult {
public String commandId;
public boolean result = true;
public boolean skipped = false;
public List<Exception> exceptions = new ArrayList<>();
public Object resultObject = null;
public ExecutionPlanUpdate planUpdate = null;
public CommandResult(String id) {
this.commandId = id;
}
public ProducerResult.CommandResult result(boolean resultValue) {
this.result = resultValue;
return this;
};
public ProducerResult.CommandResult resultObject(Object resultObjectValue) {
this.resultObject = resultObjectValue;
return this;
};
public ProducerResult.CommandResult exception(Exception exceptionValue) {
this.exceptions.add(exceptionValue);
return this;
};
}
public static ProducerResult createFailed(Exception e) {
ProducerResult result = new ProducerResult();
result.commandResult("#").exception(e).result(false);
return result;
}
protected List<CommandResult> commandResults = new LinkedList<>();
public Object getLastObject() {
if (commandResults.isEmpty())
return null;
return commandResults.get(commandResults.size()-1).resultObject;
}
public CommandResult getLastCommandResult() {
if (commandResults.isEmpty())
return null;
return commandResults.get(commandResults.size()-1);
}
public Map<String, List<Exception>> getAllExceptions(){
Map<String, List<Exception>> result = new LinkedHashMap<>();
for (CommandResult cr: commandResults)
if (!cr.exceptions.isEmpty())
result.put(cr.commandId, cr.exceptions);
return result;
}
public List<CommandResult> getCommandResults() {
return commandResults;
}
public <T> T findResultObject(Class<T> clazz){
log.debug("findResultObject : " + clazz.getName());
ListIterator<CommandResult> listIterator = commandResults.listIterator(commandResults.size());
while (listIterator.hasPrevious()) {
CommandResult cr = listIterator.previous();
log.debug("Inspecting : " + cr.commandId);
if ((cr.resultObject != null) && (clazz.isInstance(cr.resultObject))) {
log.debug("... found");
return clazz.cast(cr.resultObject);
}
log.debug("... not found");
}
return null;
}
public CommandResult commandResult(String id) {
CommandResult commandResult = new CommandResult(id);
this.commandResults.add(commandResult);
return commandResult;
}
public void addCommandResult(CommandResult commandResult) {
this.commandResults.add(commandResult);
}
}

View File

@ -0,0 +1,32 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.api;
import java.util.List;
import java.util.Map;
public interface ProducingCommandExecutor {
public String getId();
public List<String> getRequiredPredecessors();
public List<String> getDescendants();
public List<Class<?>> getAcceptedInputClasses();
public List<Class<?>> getProducedOutputClasses();
public ProducerResult execute(ProducerResult currentResult, Map<String, Object> parameters);
}

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,32 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producer-core</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: PRODUCER CORE</name>
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: PRODUCER CORE</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.core.producer.*</bundle.osgi.export.pkg>
</properties>
<dependencies>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.core.object-producing
</groupId>
<artifactId>object-producer-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>artifact-management</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,162 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.api.ProducingCommandExecutor;
public abstract class AbstractCommandExecutor implements ProducingCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(AbstractCommandExecutor.class);
public static String SKIP_INSTRUSTION = "skip";
public static String PRINT_OUTPUT_INSTRUSTION = "printOutput";
protected EntaxyProducerService entaxyProducerService;
protected String id;
protected List<String> requiredPredecessors = new ArrayList<>();
protected List<String> descendants = new ArrayList<>();
protected List<Class<?>> acceptedInputClasses = new ArrayList<>();
protected List<Class<?>> producedOutputClasses = new ArrayList<>();
protected boolean isPrintOutput = false;
protected Map<String, Object> instructions;
protected AbstractCommandExecutor(EntaxyProducerService entaxyProducerService) {
this.entaxyProducerService = entaxyProducerService;
if (this.getClass().isAnnotationPresent(CommandExecutor.class)) {
CommandExecutor commandExecutorAnnotation = this.getClass().getAnnotation(CommandExecutor.class);
this.id = commandExecutorAnnotation.id();
this.requiredPredecessors = Arrays.asList(commandExecutorAnnotation.predecessors());
this.descendants = Arrays.asList(commandExecutorAnnotation.descendants());
this.acceptedInputClasses = Arrays.asList(commandExecutorAnnotation.inputs());
this.producedOutputClasses = Arrays.asList(commandExecutorAnnotation.outputs());
}
}
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public List<String> getRequiredPredecessors() {
return requiredPredecessors;
}
public void setRequiredPredecessors(List<String> requiredPredecessors) {
this.requiredPredecessors = requiredPredecessors;
}
@Override
public List<String> getDescendants() {
return descendants;
}
public void setDescendants(List<String> descendants) {
this.descendants = descendants;
}
@Override
public List<Class<?>> getAcceptedInputClasses() {
return acceptedInputClasses;
}
public void setAcceptedInputClasses(List<Class<?>> acceptedInputClasses) {
this.acceptedInputClasses = acceptedInputClasses;
}
@Override
public List<Class<?>> getProducedOutputClasses() {
return this.producedOutputClasses;
}
public void setProducedOutputClasses(List<Class<?>> producedOutputClasses) {
this.producedOutputClasses = producedOutputClasses;
}
@Override
public ProducerResult execute(ProducerResult currentResult, Map<String, Object> instructions) {
CommandResult cr = new CommandResult(getId());
this.instructions = instructions;
setPrintOutput(instructions);
if (isSkipped(instructions))
cr.skipped = true;
else
try {
cr.result = doExecute(currentResult, cr, instructions);
} catch (Exception e) {
log.error("Error executing [" + getId() + "]", e);
cr.exception(e).result(false);
}
currentResult.addCommandResult(cr);
return currentResult;
}
protected void setPrintOutput(Map<String, Object> parameters) {
if (parameters.containsKey(PRINT_OUTPUT_INSTRUSTION)) {
Object val = parameters.get(PRINT_OUTPUT_INSTRUSTION);
if (val == null)
return;
if (val instanceof Boolean)
this.isPrintOutput = (Boolean)val;
}
}
protected void printOutput(String message) {
if (this.isPrintOutput)
// OUTPUT TO CONSOLE
System.out.println(message);
}
protected boolean isSkipped(Map<String, Object> parameters) {
if (!parameters.containsKey(SKIP_INSTRUSTION))
return false;
Object obj = parameters.get(SKIP_INSTRUSTION);
if (obj instanceof Boolean)
return (Boolean)obj;
if (obj instanceof String)
return "true".equalsIgnoreCase((String)obj);
if (obj instanceof Number)
return ((Number)obj).intValue() > 0;
return false;
}
protected abstract boolean doExecute(ProducerResult currentResult
, CommandResult commandResult
, Map<String, Object> instructions) throws Exception;
}

View File

@ -0,0 +1,35 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandExecutor {
String id();
String[] predecessors() default {};
String[] descendants() default {};
Class<?>[] inputs() default {};
Class<?>[] outputs() default {};
}

View File

@ -0,0 +1,86 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor;
import java.util.HashMap;
import java.util.Map;
public class CommandInstructions {
protected Map<String, Object> instructionsMap = new HashMap<>();
public CommandInstructions() {
super();
}
public CommandInstructions(Map<String, Object> instructionsMap) {
super();
load(instructionsMap);
}
public void load(Map<String, Object> instructionsMap) {
this.instructionsMap = instructionsMap;
}
public boolean has(String name) {
return this.instructionsMap.containsKey(name);
}
public Boolean getBoolean(String name) {
if (!this.has(name))
return null;
Object value = this.instructionsMap.get(name);
if (value instanceof Boolean)
return (Boolean)value;
if (value instanceof String)
return "true".equals(((String)value).toLowerCase());
if (value instanceof Number)
return ((Number)value).longValue() > 0;
if (value instanceof Long)
return ((Long)value).longValue() > 0;
return value!=null;
}
public Object get(String name) {
return this.instructionsMap.get(name);
}
public String getString(String name) {
if (!has(name))
return null;
Object value = instructionsMap.get(name);
return value!=null?value.toString():"";
}
public Long getLong(String name) {
if (!has(name))
return null;
Object value = instructionsMap.get(name);
if (value instanceof Number)
return ((Number)value).longValue();
return (long)-1;
}
}

View File

@ -0,0 +1,209 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
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.DependencySorter;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ExecutionPlan;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate.OPERATIONS;
import ru.entaxy.platform.core.producer.api.ExecutionTask;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
public class ProducingExecutor {
private static final Logger log = LoggerFactory.getLogger(ProducingExecutor.class);
protected static final String DEFAULT_EXECUTION_PLAN = "{'validate':{}}";
protected static final String ANY_COMMAND = "*";
protected JsonObject configuration;
protected EntaxyProducerService producerService;
protected JsonObject executionPlanJSON = JSONUtils.getJsonRootObject(DEFAULT_EXECUTION_PLAN);
protected ExecutionPlan executionPlan = null;
public ProducingExecutor(JsonObject configuration, String buildInstructions
, EntaxyProducerService producerService) throws Exception {
this.configuration = configuration;
this.producerService = producerService;
if (CommonUtils.isValid(buildInstructions)) {
executionPlanJSON = JSONUtils.getJsonRootObject(buildInstructions);
if (executionPlanJSON.entrySet().isEmpty())
executionPlanJSON = JSONUtils.getJsonRootObject(DEFAULT_EXECUTION_PLAN);
}
buildPlan();
}
protected ExecutionTask createExecutionTask(String id, Map<String, Object> parameters) {
ExecutionTask result = new ExecutionTask();
result.commandId = id;
result.instructions = parameters;
result.executor = producerService.getCommandById(result.commandId);
return result;
}
protected ExecutionTask createExecutionTask(Map<String, ExecutionTask> taskMap, String id, Map<String, Object> commandInstructions) {
if (!taskMap.containsKey(id))
taskMap.put(id, new ExecutionTask(id));
ExecutionTask result = taskMap.get(id);
result.instructions = commandInstructions;
result.executor = producerService.getCommandById(result.commandId);
return result;
}
protected void createDependency(Map<String, ExecutionTask> taskMap, String masterId, String slaveId) {
taskMap.get(slaveId).dependsOn.add(taskMap.get(masterId));
}
protected void buildPlan() throws Exception {
log.debug("building plan for execution on: \n" + configuration.toString());
log.debug("execution plan: \n" + executionPlanJSON.toString());
Map<String, ExecutionTask> taskMap = new HashMap<>();
Map<String, Object> anyCommandInstructions = new HashMap<>();
if (executionPlanJSON.has(ANY_COMMAND))
anyCommandInstructions = JSONUtils.element2map(executionPlanJSON.get(ANY_COMMAND));
List<String> neededCommands = new ArrayList<>();
for (String id: executionPlanJSON.keySet()) {
if (ANY_COMMAND.equals(id))
continue;
JsonElement jsonElement = executionPlanJSON.get(id);
Map<String, Object> commandInstructions = new HashMap<>(anyCommandInstructions);
commandInstructions.putAll(JSONUtils.element2map(jsonElement));
neededCommands.add(id);
if (createExecutionTask(taskMap, id, commandInstructions).executor == null) {
log.error("Command [{}] not found", id);
throw new Exception("Command not found: " + id);
}
}
List<String> commandsToCheck = List.copyOf(neededCommands);
List<String> newCommandsToCheck = new ArrayList<>();
// add required commands
while (!commandsToCheck.isEmpty()) {
newCommandsToCheck.clear();
for (String command: commandsToCheck) {
log.debug("Checking command [{}]", command);
for (String s: taskMap.get(command).executor.getRequiredPredecessors()) {
if (!neededCommands.contains(s)) {
log.debug("Adding command [{}]", s);
newCommandsToCheck.add(s);
neededCommands.add(s);
if (createExecutionTask(taskMap, s, anyCommandInstructions).executor == null) {
log.error("Command [{}] not found", s);
throw new Exception("Command not found: " + s);
}
}
createDependency(taskMap, s, command);
}
}
commandsToCheck = List.copyOf(newCommandsToCheck);
}
// create backward dependencies by descendants
for (String s: taskMap.keySet()) {
for (String descendant: taskMap.get(s).executor.getDescendants()) {
if (taskMap.containsKey(descendant))
createDependency(taskMap, s, descendant);
}
}
// arrange commands
executionPlan = new ExecutionPlan(new LinkedList<>(taskMap.values()));
List<ExecutionTask> sorted = DependencySorter.getSortedList(
executionPlan.tasks,
new DependencySorter.DependencyProvider<ExecutionTask>() {
@Override
public List<ExecutionTask> getDependencies(ExecutionTask inspectedObject) {
return inspectedObject.dependsOn;
}
});
executionPlan.tasks = sorted;
}
public ProducerResult execute() {
ProducerResult producerResult = new ProducerResult();
producerResult.commandResult("#plan").result(true).resultObject(executionPlan);
producerResult.commandResult("#init").result(true).resultObject(configuration);
return execute(producerResult);
}
protected ProducerResult execute(ProducerResult producerResult) {
Iterator<ExecutionTask> taskIterator = executionPlan.iterator();
while (taskIterator.hasNext()) {
ExecutionTask task = taskIterator.next();
task.executor.execute(producerResult, task.instructions);
CommandResult cr = producerResult.getLastCommandResult();
if (cr.planUpdate != null) {
try {
log.debug("Applying plan update");
List<ExecutionPlanUpdate.OPERATIONS> result = executionPlan.applyUpdate(cr.planUpdate);
producerResult.commandResult("#planUpdate").result(true).resultObject(cr.planUpdate);
if (result.contains(OPERATIONS.RESET))
producerResult.commandResult("#reset").result(true).resultObject(cr.planUpdate);
} catch (Exception e) {
log.error("Error applying plan update", e);
producerResult.commandResult("#planUpdate").result(false).resultObject(cr.planUpdate).exception(e);
}
}
}
return producerResult;
}
}

View File

@ -0,0 +1,79 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@CommandExecutor(id = "analyze", inputs = {JsonObject.class}, predecessors = {})
public class Analyze extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Analyze.class);
public Analyze(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
log.info("Executing command [{}]", getId());
JsonObject jo = currentResult.findResultObject(JsonObject.class);
printOutput("\n\n\t== ANALYZE == \n\n");
printOutput("\n\tIncoming JSON ::\n\n");
printOutput(jo.toString());
ObjectModel om = new ObjectModel();
om.load(jo);
om.checkRefs();
printOutput("\n\tObjectModel ::\n\n");
for (FactoredObject fo: om.objects)
printOutput("Object :: [" + fo.getObjectId() + "/" + fo.factoryId + ":" + fo.getObjectType() + "]");
for (FactoredObjectRef fo: om.refs)
printOutput("Reference :: [" + fo.definedIn.getObjectId() + " -> " + fo.getTargetId()
+ "; isLink=" + fo.isLink()
+ "; isExternal=" + fo.isExternal()
+ "]");
commandResult.resultObject(om);
printOutput("\n\tOutgoing JSON ::\n\n");
printOutput(om.getJsonCurrent().toString());
return true;
}
}

View File

@ -0,0 +1,151 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
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.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.ArtifactManifest;
import ru.entaxy.platform.core.artifact.Artifacts;
import ru.entaxy.platform.core.artifact.Manifested;
import ru.entaxy.platform.core.artifact.capabilities.ManifestCapabilityHelper;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.objects.EntaxyObject.HEADERS;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedHeaders;
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedList;
import ru.entaxy.platform.core.producer.executor.support.ArtifactList;
@CommandExecutor(id = "build", predecessors = {"generate"})
public class Build extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Build.class);
public Build(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
printOutput("\n\t == BUILDING ==\n");
GeneratedList generated = currentResult.findResultObject(GeneratedList.class);
if (generated == null) {
log.info("Nothing to generate");
return true;
}
ArtifactList artifactList = new ArtifactList();
for (Generated g: generated) {
if (g == null)
continue;
Artifact artifact = Artifacts.fromGenerated(g);
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|| !CommonUtils.isValid(artifact.getCategory())) {
log.info("Artifact is not buildable");
continue;
}
log.info("Built artifact of category [{}]", artifact.getCategory());
Map<String, String> headers = GeneratedHeaders.getHeaders(g.getProperties()).getAsStringMap();
String mainObjectValue = headers.get(HEADERS.MAIN_OBJECT);
if (!CommonUtils.isValid(mainObjectValue))
throw new Exception("Main object not found");
String[] mainObjectData = mainObjectValue.split(":");
if (mainObjectData.length<2)
throw new Exception("Main object not complete: [" + mainObjectValue + "]");
String versionPolicy = g.getProperties().getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY,
instructions.getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY
, ""))
.toString();
String timestamp = g.getProperties().getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.TIMESTAMP,
instructions.getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.TIMESTAMP
, ""))
.toString();
artifact.getCoordinates()
.groupId(mainObjectData[1])
.artifactId(mainObjectData[0])
.version("1")
.versionPolicy(versionPolicy)
.timestamp(timestamp);
if (artifact instanceof Manifested) {
ArtifactManifest manifest = ((Manifested)artifact).getManifest();
manifest.getCustomAttributes().putAll(headers);
// Generate provided capabilities for every included object
ManifestCapabilityHelper helper = new ManifestCapabilityHelper(manifest);
String objectsValue = headers.getOrDefault(HEADERS.GENERATED_OBJECTS, "");
if (CommonUtils.isValid(objectsValue)) {
String[] objects = objectsValue.split(",");
for (int i=0; i<objects.length; i++) {
String[] objectData = objects[i].split(":");
if (objectData.length<2)
continue;
String objectId = objectData[0];
String objectType = objectData[1];
if (!CommonUtils.isValid(objectId) || !CommonUtils.isValid(objectType))
continue;
objectId = objectId.trim();
objectType = objectType.trim();
Map<String, Object> attributes = null;
if (g.getProperties().containsKey(FIELDS.FIELDS_TO_PUBLISH)) {
Object map = g.getProperties().get(FIELDS.FIELDS_TO_PUBLISH);
if (map != null) {
attributes = (Map<String, Object>)((Map<String, Object>)map).get(objectId);
}
}
helper.provideCapability(objectType).attributes(attributes);
}
helper.save();
}
}
artifact.getProperties().putAll(g.getProperties());
artifactList.add(artifact);
printOutput("\n\t == " + artifact.getCoordinates().toString() + " ==\n");
printOutput(new String(artifact.asByteArray()));
printOutput("\n\t == \n");
}
commandResult.resultObject(artifactList);
return true;
}
}

View File

@ -0,0 +1,79 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import java.util.stream.Collectors;
import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
import ru.entaxy.platform.core.artifact.service.ArtifactService;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.support.ArtifactList;
import ru.entaxy.platform.core.producer.executor.support.ArtifactsHelper;
import ru.entaxy.platform.core.producer.executor.support.DeployedArtifactList;
@CommandExecutor(id = "deploy", predecessors = {"build"})
public class Deploy extends AbstractCommandExecutor {
public static final String DEPLOY_LOCAL_INSTRUCTION = "deployLocal";
public Deploy(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
boolean deployLocal = false;
Object deployLocalValue = instructions.get(DEPLOY_LOCAL_INSTRUCTION);
if (deployLocalValue != null)
if (deployLocalValue instanceof Boolean)
deployLocal = (Boolean)deployLocalValue;
ArtifactList artifactList = currentResult.findResultObject(ArtifactList.class);
DeployedArtifactList deployedArtifactList = new DeployedArtifactList();
ArtifactService artifactService = ArtifactsHelper.getInstance().getArtifactService();
for (Artifact artifact: artifactList) {
DeployedArtifact da = deployLocal
?artifactService.deployLocal(artifact)
:artifactService.deployShared(artifact);
deployedArtifactList.add(da);
}
printOutput("\n\n\t== DEPLOY ==\n");
printOutput("DEPLOYED: ["
+ deployedArtifactList.stream().map(da->da.getLocation()).collect(Collectors.joining(","))
+ "]");
commandResult.resultObject(deployedArtifactList);
return true;
}
}

View File

@ -0,0 +1,548 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
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.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.CONFIGURATION.OUTPUTS;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.FieldInfo;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.RefFieldInfo;
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.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
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;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
import ru.entaxy.platform.core.producer.impl.FieldInfoImpl;
import ru.entaxy.platform.core.producer.impl.RefFieldInfoImpl;
@CommandExecutor(id = "enrich", predecessors = {"layout"})
public class Enrich extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Enrich.class);
public Enrich(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
// TODO Auto-generated constructor stub
}
// TODO move to FieldInfo
protected boolean isLookup(FieldInfo fi) {
if (fi.getJsonOrigin().has("lookup")) {
String lookup = fi.getJsonOrigin().get("lookup").getAsString();
return CommonUtils.isValid(lookup);
}
return false;
}
// TODO move to FieldInfo
public String getLookup(FieldInfo fi) {
return fi.getJsonOrigin().has("lookup")
?fi.getJsonOrigin().get("lookup").getAsString()
:null;
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
int count = 15;
if (!instructions.containsKey("_count")) {
instructions.put("_count", count);
}
if (instructions.get("_count") instanceof Integer)
count = (Integer)instructions.get("_count");
else if (instructions.get("_count") instanceof Number)
count = ((Number)instructions.get("_count")).intValue();
count--;
printOutput("\n\n\t== ENRICH == #" + count + " ==\n\n");
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
objectModel.startTracking();
JsonObject incomingJson = objectModel.getJsonCurrent().deepCopy();
Gson gson = new Gson();
// enrich type to ensure we can resolve refs
for (FactoredObject fo: objectModel.objects) {
// skip proxies
if (fo instanceof FactoredObjectProxy)
continue;
String factoryId = fo.factoryId;
EntaxyFactory factory = entaxyProducerService.findFactoryById(factoryId);
if (factory == null)
throw new Exception("Factory not found: [" + factoryId + "]");
String objectType = fo.getObjectType();
if (!CommonUtils.isValid(objectType)) {
fo.setObjectType(factory.getFactoryType());
objectModel.setDirty();
}
}
// enrich fields
for (FactoredObject fo: objectModel.objects) {
// skip proxies
if (fo instanceof FactoredObjectProxy)
continue;
String factoryId = fo.factoryId;
EntaxyFactory factory = entaxyProducerService.findFactoryById(factoryId);
List<FieldInfo> delayed = new LinkedList<>();
List<String> processedFieldNames = new LinkedList<>();
JsonObject objectOrigin = fo.origin;
if (JSONUtils.setValue(objectOrigin, FIELDS.PROPERTIES, new JsonObject(), true)) {
printOutput("[DIRTY] CREATED 'properties' for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectModel.setDirty();
}
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
List<FieldInfo> factoryFields = factory.getFields(OUTPUTS.OUTPUT_TYPE_INIT);
for (FieldInfo fi: factoryFields) {
FieldInfo fieldInfo = fi;
log.info("\n ITERATING FOR FIELD: " + fi.getName() + "\n" + fi.getJsonOrigin());
if (FIELDS.OBJECT_ID.equals(fi.getName())
|| FIELDS.OBJECT_TYPE.equals(fi.getName()))
continue;
// check if lookup
if (isLookup(fi)) {
String lookup = getLookup(fi);
log.info("\n LOOKUP FIELD: " + fi.getName() + " -> " + lookup);
// replace lookup with corresponding ref
Optional<FieldInfo> toLookupOpt = factoryFields.stream()
.filter(f -> lookup.equals(f.getName()))
.findFirst();
if (!toLookupOpt.isPresent()) {
// field to lookup not found
log.error("Factory configuration error: loooked up field [{}] referenced by [{}] not found in factory [{}]"
, lookup
, fi.getName()
, factory.getFactoryId());
continue;
}
FieldInfo toLookup = toLookupOpt.get();
RefFieldInfoImpl fieldInfoImpl = new RefFieldInfoImpl();
fieldInfoImpl.name(fi.getName())
.description(fi.getDescription())
.displayName(fi.getDisplayName())
.immutable(fi.isImmutable())
.required(fi.isRequired());
fieldInfoImpl.refField(
fi.getJsonOrigin().has(FIELDS.REF_FIELD)
?fi.getJsonOrigin().get(FIELDS.REF_FIELD).getAsString()
:""
)
.refByValueOnly(true)
.backRef(false);
fieldInfoImpl.setConditional(fi.isConditional());
fieldInfoImpl.setCondition(fi.getCondition());
fieldInfoImpl.setRef(true);
fieldInfoImpl.setType(toLookup.getType());
JsonObject lookupJson = fi.getJsonOrigin().deepCopy();
JsonObject lookedUpJson = toLookup.getJsonOrigin();
for (Entry<String, JsonElement> entry: lookedUpJson.entrySet()) {
if (lookupJson.has(entry.getKey()))
lookupJson.remove(entry.getKey());
lookupJson.add(entry.getKey(), entry.getValue());
}
fieldInfoImpl.setJsonOrigin(lookupJson);
log.info("\n LOOKUP FIELD JSON: \n" + lookupJson.toString());
fieldInfo = fieldInfoImpl;
if (!processedFieldNames.contains(lookup) || fi.isConditional()) {
delayed.add(fieldInfo);
continue;
}
}
// check if conditional
if (fi.isConditional()) {
delayed.add(fi);
continue;
}
processField(objectModel, fieldInfo, fo, gson);
processedFieldNames.add(fieldInfo.getName());
}
int delayedCount = 0;
while (delayedCount != delayed.size()) {
List<FieldInfo> toRemove = new ArrayList<>();
delayedCount = delayed.size();
for (FieldInfo fi: delayed) {
// first check conditionals
if (fi.isConditional()) {
String condition = fi.getCondition();
if (condition.startsWith("${"))
condition = condition.substring(2, condition.lastIndexOf("}"));
if (!objectProperties.has(condition))
continue;
Object conditionValue = JSONUtils.element2object(objectProperties.get(condition));
if (conditionValue == null) {
continue;
} else if (conditionValue instanceof String) {
if (!"true".equalsIgnoreCase((String)conditionValue)) {
toRemove.add(fi);
continue;
}
} else if (conditionValue instanceof Number) {
if (((Number)conditionValue).doubleValue()<=0) {
toRemove.add(fi);
continue;
}
} else if (conditionValue instanceof Boolean) {
if (!(Boolean)conditionValue) {
toRemove.add(fi);
continue;
}
}
}
// then check lookups
if (isLookup(fi)) {
if (!processedFieldNames.contains(getLookup(fi))) {
continue;
}
}
// we're still here so process
processField(objectModel, fi, fo, gson);
processedFieldNames.add(fi.getName());
}
delayed.removeAll(toRemove);
}
}
if (objectModel.stopTracking() && count>0) {
// 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();
}
instructions.put("_count", count);
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;
}
protected boolean processField(ObjectModel objectModel, FieldInfo fi, FactoredObject fo, Gson gson) {
log.info("\nPROCESSING FIELD: " + fi.getName());
if (fi.isRef()) {
log.info("\nPROCESSING REF: " + fi.getName());
return processRef(objectModel, (RefFieldInfo)fi, fo, gson);
}
boolean result = false;
JsonObject objectOrigin = fo.origin;
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
boolean exists = objectProperties.has(fi.getName());
if (!exists) {
if (fi.isRequired()) {
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectProperties.add(fi.getName(), fi.getJsonOrigin().get(FIELDS.DEFAULT_VALUE));
objectModel.setDirty();
result = true;
}
}
return result;
}
protected boolean processRef(ObjectModel objectModel, RefFieldInfo fi, FactoredObject fo, Gson gson) {
boolean result = false;
JsonObject objectOrigin = fo.origin;
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
boolean exists = objectProperties.has(fi.getName());
if (!exists) {
if (fi.isRequired()) {
if (fi.isBackRef()) {
// it's a backRef, so we'll try to find object of the given type
// referencing current object
List<FactoredObject> candidates = fo.references.stream()
.filter(ref->!ref.isBackRef())
.map(ref->ref.definedIn)
.filter(obj->fi.getType().equals(obj.getObjectType()))
.collect(Collectors.toList());
if (candidates.size()>0) {
// we found candidates, so just add ref to first one
// no matter what object is there
// 'cause the ref being backRef won't be ever generated
FactoredObjectRef ref = new FactoredObjectRef(objectModel, candidates.get(0));
ref.definedIn = fo;
fo.embed(ref);
ref.setBackRef(true);
ref.setResolved(true);
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectProperties.add(fi.getName(), ref.origin);
result = true;
} else {
// try to use default value
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectProperties.add(fi.getName(), fi.getJsonOrigin().get(FIELDS.DEFAULT_VALUE));
objectModel.setDirty();
result = true;
}
} else {
// it's a direct ref
FactoredObject candidate = null;
// try to find by backRef
List<FactoredObjectRef> backrefs = objectModel.refs.stream()
.filter(ref->
(ref.isBackRef()
&& (ref.getTargetObject().equals(fo))
&& (ref.definedIn.getObjectType().equals(fi.getType()))
)
)
.collect(Collectors.toList());
if (backrefs.size()>0) {
// we can use any
candidate = backrefs.get(0).definedIn;
} else {
// try to find objects of required type defined in current
List<FactoredObject> candidates = objectModel.objects
.stream()
.filter(
obj->((obj != fo) && (obj.getObjectType().equals(fi.getType())))
)
.collect(Collectors.toList());
// we can use the only one
if (candidates.size() == 1)
candidate = candidates.get(0);
else if (candidates.size()>1) {
// search for defined in current
candidates = candidates.stream().filter(c->c.isDefinedIn(fo))
.collect(Collectors.toList());
if (candidates.size()==1)
candidate = candidates.get(0);
}
}
if (candidate != null) {
FactoredObjectRef ref = new FactoredObjectRef(objectModel, candidate);
ref.definedIn = fo;
fo.embed(ref);
ref.origin.addProperty(FIELDS.IS_REF_BY_VALUE_ONLY, fi.isRefByValueOnly());
ref.origin.addProperty(FIELDS.REF_FIELD, fi.getRefField());
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectProperties.add(fi.getName(), ref.origin);
objectModel.setDirty();
result = true;
} else {
/*
if (fi.getJsonOrigin().has(FIELDS.DEFAULT_VALUE)) {
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectProperties.add(fi.getName(), fi.getJsonOrigin().get(FIELDS.DEFAULT_VALUE));
objectModel.setDirty();
result = true;
} else { */
// we just create a ref to nothing
// hoping it will be enriched next time
JsonObject refCopy = fi.getJsonOrigin().deepCopy();
if (isLookup(fi)) {
// remove default targetId, 'cause it will be resolved on next enrich
refCopy.remove(FactoredObjectRef.TARGET_ID_FIELD);
}
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
printOutput("\t" + refCopy.toString());
objectProperties.add(fi.getName(), refCopy);
objectModel.setDirty();
result = true;
//}
}
}
}
} else {
// we found something where must be ref
JsonElement currentValue = objectProperties.get(fi.getName());
JsonObject refCopy = fi.getJsonOrigin().deepCopy();
if (currentValue.isJsonObject()) {
// this is some object
printOutput("CURRENT VALUE [" + currentValue.toString() + "] IS OBJECT IN " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
JsonObject currentObject = currentValue.getAsJsonObject();
if (currentObject.has(FIELDS.IS_REF)) {
String targetType = currentObject.has(FactoredObjectRef.TARGET_TYPE_FIELD)
?currentObject.get(FactoredObjectRef.TARGET_TYPE_FIELD).getAsString()
:null;
if (!CommonUtils.isValid(targetType)){
String refType = fi.getType();
targetType = CommonUtils.isValid(refType)?refType:"*";
currentObject.remove(FactoredObjectRef.TARGET_TYPE_FIELD);
currentObject.addProperty(FactoredObjectRef.TARGET_TYPE_FIELD, targetType);
objectModel.setDirty();
}
if (!currentObject.has(FIELDS.IS_REF_BY_VALUE_ONLY)
|| !currentObject.has(FIELDS.REF_FIELD)
|| !currentObject.has(FIELDS.IS_BACK_REF))
{
currentObject.addProperty(FIELDS.IS_REF_BY_VALUE_ONLY, fi.isRefByValueOnly());
currentObject.addProperty(FIELDS.REF_FIELD, fi.getRefField());
currentObject.addProperty(FIELDS.IS_BACK_REF, fi.isBackRef());
printOutput("[DIRTY] UPDATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectModel.setDirty();
}
if (isLookup(fi)) {
String lookup = getLookup(fi);
JsonElement lookupValue = objectProperties.get(lookup);
if (lookupValue.isJsonObject()) {
JsonObject lookupObject = lookupValue.getAsJsonObject();
if (lookupObject.has(FactoredObjectRef.TARGET_ID_FIELD)) {
String lookupTargetId = lookupObject.get(FactoredObjectRef.TARGET_ID_FIELD).getAsString();
String lookupTargetType = lookupObject.get(FactoredObjectRef.TARGET_TYPE_FIELD).getAsString();
String currentTargetId = currentObject.has(FactoredObjectRef.TARGET_ID_FIELD)
?currentObject.get(FactoredObjectRef.TARGET_ID_FIELD).getAsString()
:"";
String currentTargetType = currentObject.has(FactoredObjectRef.TARGET_TYPE_FIELD)
?currentObject.get(FactoredObjectRef.TARGET_TYPE_FIELD).getAsString()
:"";
if (
(!lookupTargetId.equals(currentTargetId) && currentTargetType.equals(lookupTargetType))
|| !CommonUtils.isValid(currentTargetId)
) {
currentObject.remove(FactoredObjectRef.TARGET_ID_FIELD);
currentObject.add(FactoredObjectRef.TARGET_ID_FIELD, lookupObject.get(FactoredObjectRef.TARGET_ID_FIELD));
printOutput("[DIRTY] UPDATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]"
+ "\n\tSET LOOKUP TARGET ID TO ["
+ lookupObject.get(FactoredObjectRef.TARGET_ID_FIELD).toString()
+ "]");
objectModel.setDirty();
}
}
}
}
result = true;
} else if (currentObject.has(FIELDS.FACTORY_ID)) {
// it will be replaced with reference on next layout
printOutput("[DIRTY] FOUND OBJECT " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectModel.setDirty();
result = true;
}
} else {
printOutput("CURRENT VALIE [" + currentValue.toString() + "] IS NOT OBJECT IN " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
}
if (!result) {
// we have something which is not a ref and not a object to produce
// we'll treat it as resolved ref value
refCopy.remove(FIELDS.DEFAULT_VALUE);
refCopy.add(FactoredObjectRef.TARGET_VALUE_FIELD, currentValue);
refCopy.addProperty(FactoredObjectRef.IS_RESOLVED_FIELD, true);
printOutput("[DIRTY] CONSIDER VALUE [" + currentValue.toString() + "] AS RESOLVED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
objectModel.setDirty();
result = true;
}
}
return result;
}
}

View File

@ -0,0 +1,78 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.generationmodel.AbstractTask;
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedList;
import ru.entaxy.platform.core.producer.executor.generationmodel.GenerationModel;
@CommandExecutor(id = "generate", predecessors = {"validate", "pre-generate"})
public class Generate extends AbstractCommandExecutor {
public Generate(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
// TODO Auto-generated constructor stub
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
GenerationModel generationModel = currentResult.findResultObject(GenerationModel.class);
// generate
this.printOutput("\n\t == Execution ==\n");
for (AbstractTask at: generationModel.getTasks()) {
at.setPrintOutput(isPrintOutput);
at.execute(currentResult, commandResult, entaxyProducerService, instructions);
this.printOutput("\n :: Result ::\n");
if (at.getGeneratedResult()==null)
this.printOutput("-> NOTHING");
else {
Generated g = at.getGeneratedResult();
this.printOutput("\tTYPE :: [" + g.getType() + "]");
this.printOutput("\tCONTENT :: \n\n");
if (g.getObject() == null)
this.printOutput("-> EMPTY\n\n");
else
this.printOutput(g.getObject().toString());
}
this.printOutput("\n ::\n");
}
this.printOutput("\n\t ==\n");
// collect result
GeneratedList resultObject = new GeneratedList();
for (AbstractTask at: generationModel.getTasks())
resultObject.add(at.getGeneratedResult());
commandResult.resultObject(resultObject);
return true;
}
}

View File

@ -0,0 +1,145 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import org.osgi.framework.Constants;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.artifact.Blueprint;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
import ru.entaxy.platform.core.artifact.installer.builder.ClusterInstaller;
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
import ru.entaxy.platform.core.artifact.installer.builder.Installer;
import ru.entaxy.platform.core.artifact.installer.builder.LocalInstaller;
import ru.entaxy.platform.core.artifact.installer.builder.typed.BlueprintInstaller;
import ru.entaxy.platform.core.artifact.service.ArtifactService;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandInstructions;
import ru.entaxy.platform.core.producer.executor.support.ArtifactsHelper;
import ru.entaxy.platform.core.producer.executor.support.DeployedArtifactList;
import ru.entaxy.platform.core.producer.executor.support.InstallationResultList;
@CommandExecutor(id = "install", predecessors = "deploy")
public class Install extends AbstractCommandExecutor {
public static final String INSTALL_LOCAL_INSTRUCTION = "installLocal";
public static final String UPDATE_INSTRUCTION = "update";
public static final String INSTALL_ONLY_IF_MISSING_INSTRUCTION = "installOnlyIfMissing";
public Install(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
CommandInstructions commandInstructions = new CommandInstructions(instructions);
boolean installLocal =
commandInstructions.has(INSTALL_LOCAL_INSTRUCTION)
?commandInstructions.getBoolean(INSTALL_LOCAL_INSTRUCTION)
:false;
boolean installOnlyIfMissing =
commandInstructions.has(INSTALL_ONLY_IF_MISSING_INSTRUCTION)
?commandInstructions.getBoolean(INSTALL_ONLY_IF_MISSING_INSTRUCTION)
:false;
String update =
commandInstructions.has(UPDATE_INSTRUCTION)
?commandInstructions.getString(UPDATE_INSTRUCTION)
:null;
Object installLocalValue = instructions.get(INSTALL_LOCAL_INSTRUCTION);
if (installLocalValue != null)
if (installLocalValue instanceof Boolean)
installLocal = (Boolean)installLocalValue;
DeployedArtifactList deployedArtifactList = currentResult.findResultObject(DeployedArtifactList.class);
InstallationResultList installationResultList = new InstallationResultList();
ArtifactService artifactService = ArtifactsHelper.getInstance().getArtifactService();
for (DeployedArtifact da: deployedArtifactList) {
InstallationResult result = null;
Installer<?> installer = null;
printOutput("-> Installing artifact: [" + da.getArtifact().getCoordinates().toString() + "]");
if (installLocal) {
LocalInstaller localInstaller = artifactService.installers().local()
.artifact(da);
installer = localInstaller;
printOutput("-> Installing locally");
} else {
ClusterInstaller clusterInstaller = artifactService.installers().cluster()
.artifact(da);
installer = clusterInstaller;
printOutput("-> Installing clustered");
}
// TODO add support for other types when they appear
if (da.getArtifact().getCategory().equals(Blueprint.ARTIFACT_CATEGORY_BLUEPRINT)) {
// we're installing blueprint
printOutput("-> Installing: " + da.getArtifact().getCategory());
BlueprintInstaller blueprintInstaller = installer.typed(BlueprintInstaller.class);
if (installOnlyIfMissing)
blueprintInstaller.installOnlyIfMissing();
if (update != null) {
if (!CommonUtils.isValid(update)) {
update = da
.getArtifact().getProperties()
.getOrDefault(Constants.BUNDLE_SYMBOLICNAME, "")
.toString();
}
blueprintInstaller.update(update);
}
result = blueprintInstaller.start().install();
} else {
printOutput("-> Unknown category: " + da.getArtifact().getCategory());
}
if (result != null) {
for (String key: da.getArtifact().getProperties().keySet())
result.getProperties().putIfAbsent(key, da.getArtifact().getProperties().get(key));
// TODO imrove Coordinates: add "asMap" method
result.getProperties().put("artifact.artifactId", da.getArtifact().getCoordinates().getArtifactId());
result.getProperties().put("artifact.groupId", da.getArtifact().getCoordinates().getGroupId());
result.getProperties().put("artifact.version", da.getArtifact().getCoordinates().getVersion());
result.getProperties().put("artifact.type", da.getArtifact().getCoordinates().getType());
result.getProperties().put("artifact.classifier", da.getArtifact().getCoordinates().getClassifier());
installationResultList.add(result);
}
}
commandResult.resultObject(installationResultList);
return true;
}
}

View File

@ -0,0 +1,64 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@CommandExecutor(id = "layout", predecessors = {"analyze"})
public class Layout extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Layout.class);
public Layout(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
log.debug("Executing command [{}]", getId());
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
printOutput("\n\n\t== LAYOUT == \n\n");
printOutput("\n\tIncoming JSON ::\n\n");
printOutput(objectModel.getJsonCurrent().toString());
log.debug(" -- INCOMING JSON --\n" + objectModel.getJsonCurrent().toString());
objectModel.layout();
log.debug(" -- OUTGOING JSON --\n" + objectModel.getJsonCurrent().toString());
commandResult.resultObject(objectModel);
printOutput("\n\tOutgoing JSON ::\n\n");
printOutput(objectModel.getJsonCurrent().toString());
return true;
}
}

View File

@ -0,0 +1,58 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.generationmodel.AbstractTask;
import ru.entaxy.platform.core.producer.executor.generationmodel.GenerationModel;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@CommandExecutor(id = "pre-generate", predecessors = {"validate"})
public class PrepareGenerate extends AbstractCommandExecutor {
public PrepareGenerate(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
GenerationModel generationModel = new GenerationModel(objectModel);
generationModel.load();
// print plan
this.printOutput("\n\t == Generation plan ==\n");
for (AbstractTask at: generationModel.getTasks())
this.printOutput(at.getInfo());
commandResult.resultObject(generationModel);
return true;
}
}

View File

@ -0,0 +1,112 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObjectStorage;
import ru.entaxy.platform.base.objects.EntaxyObjectStorageService;
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.support.InstallationResultList;
@CommandExecutor(id = "store", predecessors = "install")
public class Store extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Store.class);
protected EntaxyObjectStorageService objectStorageService;
public Store(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
try {
objectStorageService = OSGIUtils.services().ofClass(EntaxyObjectStorageService.class).get();
} catch (Exception e) {
log.warn("EntaxyObjectStorageService not found yet", e);
}
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
InstallationResultList installationResultList = currentResult.findResultObject(InstallationResultList.class);
if (objectStorageService == null)
objectStorageService = OSGIUtils.services().ofClass(EntaxyObjectStorageService.class).get();
for (InstallationResult installationResult: installationResultList) {
printOutput("\n -- INSTALLATION RESULT ::"
+ "\n\t" + installationResult.getResult().toString()
+ "\n\tproperties:"
+ (installationResult.getProperties()==null
?"\n\t\t<EMPTY>"
:installationResult.getProperties().entrySet().stream()
.map(entry->
"\n\t\t[" + entry.getKey() + "] = ["
+ (entry.getValue()==null
?""
:(entry.getValue() instanceof DeployedArtifact
?"DeployedArtifact :: " + (
((DeployedArtifact)entry.getValue()).getArtifact()
.getProperties().entrySet().stream()
.map(e->
"\n\t\t\t[" + e.getKey() + "] = ["
+ (e.getValue()==null
?""
:e.getValue().toString()) + "]"
).collect(Collectors.joining())
)
:entry.getValue().toString()) + "]"
)
).collect(Collectors.joining())
)
);
EntaxyObjectStorage objectStorage = objectStorageService.getObjectStorage(
installationResult.getProperties()
.getOrDefault(EntaxyObject.FIELDS.OBJECT_TYPE, "").toString()
);
if (objectStorage == null) {
log.warn("Storage not found for type: [" + installationResult.getProperties()
.getOrDefault(EntaxyObject.FIELDS.OBJECT_TYPE, "").toString() + "]");
continue;
}
objectStorage.store(installationResult.getProperties());
}
return true;
}
}

View File

@ -0,0 +1,53 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.commands;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@CommandExecutor(id = "validate", predecessors = {"enrich", "layout"})
public class Validate extends AbstractCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(Validate.class);
public Validate(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
log.info("Executing command [{}]", getId());
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
// TODO check ObjectModel.objects & .refs for
// - factory exists
// - output supported
return true;
}
}

View File

@ -0,0 +1,33 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
public abstract class AbstractObjectTask extends AbstractTask {
public FactoredObject origin;
public AbstractObjectTask(FactoredObject factoredObject) {
this.origin = factoredObject;
}
}

View File

@ -0,0 +1,32 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
public abstract class AbstractRefTask extends AbstractTask {
protected FactoredObjectRef objectRef;
protected AbstractRefTask(FactoredObjectRef objectRef) {
this.objectRef = objectRef;
}
}

View File

@ -0,0 +1,89 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
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;
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();
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;
}
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

@ -0,0 +1,82 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
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.Calculation;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
public class CalculateTask extends AbstractObjectTask {
private static final Logger log = LoggerFactory.getLogger(CalculateTask.class);
public static boolean hasCalculations(FactoredObject factoredObject) {
return factoredObject.getInternals().stream().filter(obj -> (obj instanceof Calculation))
.count() > 0;
}
public CalculateTask(FactoredObject factoredObject) {
super(factoredObject);
}
@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);
System.out.println("CALCULATION RESOLVED TO :: " + result);
System.out.println("\n REPLACE"
+ "\n\t" + calculation.origin
+ "\n\tWITH :: " + (new Gson()).toJsonTree(result)
+ "\n\tAT :: " + calculation.relativePath);
JSONUtils.replaceValue(origin.origin, calculation.relativePath, (new Gson()).toJsonTree(result));
}
return true;
}
}

View File

@ -0,0 +1,56 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.support.JSONUtils;
public class DefaultObjectDataResolver implements ObjectDataResolver {
@Override
public String getSupportedObjectType() {
return "*";
}
@Override
public Object resolve(EntaxyObject sourceObject, String propertyName) {
JsonObject jsonObject = JSONUtils.getJsonRootObject(sourceObject.getConfiguration());
if (jsonObject.has(propertyName))
return JSONUtils.element2object(jsonObject.get(propertyName));
return resolveNotRoot(sourceObject, propertyName, jsonObject);
}
protected Object resolveNotRoot(EntaxyObject sourceObject, String propertyName, JsonObject jsonRoot) {
if (!jsonRoot.has(FIELDS.PROPERTIES))
return null;
JsonElement propertiesElement = jsonRoot.get(FIELDS.PROPERTIES);
if (!propertiesElement.isJsonObject())
return null;
JsonObject properties = propertiesElement.getAsJsonObject();
if (!properties.has(propertyName))
return null;
return JSONUtils.element2object(properties.get(propertyName));
}
}

View File

@ -0,0 +1,122 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.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.FactoredObjectProxy;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
public class GenerateRefTask extends AbstractRefTask {
protected GenerateRefTask(FactoredObjectRef objectRef) {
super(objectRef);
}
@Override
public String getInfo() {
return "GENERATE-REF " + "[" + objectRef.getTargetId() + "] :: " + objectRef.factoryId;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
FactoredObject targetObject = this.objectRef.getTargetObject();
if (targetObject != null) {
if (targetObject instanceof FactoredObjectProxy) {
EntaxyObject target = ObjectResolveHelper.getInstance().findObject(
this.objectRef.getTargetId(),
this.objectRef.getTargetType());
if (target == null)
throw new IllegalArgumentException("Object not found: ["
+ this.objectRef.getTargetId()
+ ":"
+ this.objectRef.getTargetType()
+ "]");
JsonObject targetConfig = JSONUtils.getJsonRootObject(target.getConfiguration()).deepCopy();
JsonObject currentConfig = this.objectRef.origin;
JSONUtils.mergeObjects(currentConfig, targetConfig);
// System.out.println("\n\n\tGENERATING REF WITH CONFIG: \n\t" + targetConfig);
String factoryId = targetConfig.has(FIELDS.FACTORY_ID)
?targetConfig.get(FIELDS.FACTORY_ID).getAsString()
:"";
String factoryType = targetConfig.has(FIELDS.OBJECT_TYPE)
?targetConfig.get(FIELDS.OBJECT_TYPE).getAsString()
:"";
if (!CommonUtils.isValid(factoryId) || !CommonUtils.isValid(factoryType))
throw new IllegalArgumentException("Factory not defined for object: ["
+ this.objectRef.getTargetId()
+ ":"
+ this.objectRef.getTargetType()
+ "]");
Map<String, Object> effectiveProperties = createEffectiveProperties(targetConfig, instructions);
this.generatedResult = producerService.getProducerForType(factoryType).getFactoryById(factoryId)
.generate(EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_REF
, EntaxyFactory.SCOPE.PRIVATE.label
, effectiveProperties);
}
}
return true;
}
protected Map<String, Object> createEffectiveProperties(JsonObject config, Map<String, Object> instructions){
Map<String, Object> result = new HashMap<>();
result.put(GenerateTask.INSTRUCTIONS_FIELD, instructions);
JsonElement effectiveProperties = config.has(FIELDS.PROPERTIES)
?config.get(FIELDS.PROPERTIES)
:new JsonObject();
if (effectiveProperties.isJsonObject()) {
JsonObject jobj = effectiveProperties.getAsJsonObject();
for (Entry<String, JsonElement> entry: config.deepCopy().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;
}
@Override
public boolean isFinal() {
return false;
}
}

View File

@ -0,0 +1,146 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.slf4j.Logger;
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.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;
public class GenerateTask extends AbstractObjectTask {
private static final Logger log = LoggerFactory.getLogger(GenerateTask.class);
public static final String INSTRUCTIONS_FIELD = "##instructions";
public static final String GENERATION_PROPERTIES_FIELD = "##generation";
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 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.getFactoryId(), f.getFactoryType());
factoryType = f.getFactoryType();
} 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);
this.generatedResult = producerService.getProducerForType(factoryType).getFactoryById(factoryId).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);
}
GeneratedHeaders headers = GeneratedHeaders.getHeaders(this.generatedResult.getProperties());
headers.set(HEADERS.MAIN_OBJECT, origin.getObjectId() + ":" + factoryType);
headers.append(HEADERS.GENERATED_OBJECTS, origin.getObjectId() + ":" + factoryType);
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_TYPE, factoryType);
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_FACTORY_ID, factoryId);
// headers.append(GeneratedHeaders.HEADER_OBJECT_ID, origin.getObjectId());
// headers.append(GeneratedHeaders.HEADER_OBJECT_TYPE, factoryType);
headers.append(HEADERS.GENERATED_OBJECTS_CONFIG
, Base64.getEncoder().encodeToString(origin.origin.toString().getBytes()));
this.generationProperties.clear();
this.generationProperties.putAll(effectiveProperties);
this.generatedResult.getProperties().put(GENERATION_PROPERTIES_FIELD, new HashMap<String, Object>(this.generationProperties));
return true;
}
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

@ -0,0 +1,85 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class GeneratedHeaders {
public static final String HEADERS_PROPERTY = "##headers";
public static GeneratedHeaders getHeaders(Map<String, Object> properties) {
if (!properties.containsKey(HEADERS_PROPERTY))
properties.put(HEADERS_PROPERTY, new GeneratedHeaders());
return (GeneratedHeaders)properties.get(HEADERS_PROPERTY);
}
Map<String, Object> headers = new HashMap<>();
public void set(String name, Object value) {
this.headers.put(name, value);
}
public void append(String name, Object value) {
if (!headers.containsKey(name))
headers.put(name, new LinkedList<Object>());
else {
Object obj = headers.get(name);
if (!(obj instanceof List<?>)) {
List<Object> list = new LinkedList<Object>();
list.add(obj);
}
}
List<Object> list = (List<Object>)headers.get(name);
list.add(value);
}
public Map<String, String> getAsStringMap(){
Map<String, String> result = new HashMap<>();
for (Entry<String, Object> entry: headers.entrySet())
result.put(entry.getKey(), getValueAsString(entry.getValue()));
return result;
}
protected String getValueAsString(Object value) {
if (value == null)
return "";
if (value instanceof Map<?,?>)
return getMapValueAsString((Map<?,?>)value);
if (value instanceof List<?>)
return getListValueAsString((List)value);
return value.toString();
}
protected String getMapValueAsString(Map<?,?> value) {
return "[" + value.entrySet().stream().filter(e -> e.getKey()!=null)
.map(e -> e.getKey().toString()+"="+getValueAsString(e.getValue()))
.collect(Collectors.joining(",")) + "]";
}
protected String getListValueAsString(List<?> value) {
return value.stream().map(obj->getValueAsString(obj)).collect(Collectors.joining(","));
}
}

View File

@ -0,0 +1,36 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.Collections;
import org.apache.commons.collections4.list.AbstractLinkedList;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
public class GeneratedList extends AbstractLinkedList<Generated> {
public GeneratedList() {
// to avoid NPE we must either call constructor with parameters
// or call init() in constructor
super(Collections.emptyList());
}
}

View File

@ -0,0 +1,138 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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;
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) {
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);
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);
// 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())
.collect(Collectors.toList());
for (FactoredObjectRef embeddedRef: embeddedRefs) {
if (!embeddedRef.isLink()) {
localPreTasks.add(new ResolveRefTask(embeddedRef));
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);
currentTasks.add(generateTask);
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 List<AbstractTask> getTasks() {
return tasks;
}
}

View File

@ -0,0 +1,106 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
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.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergeHelper;
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();
}
@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();
}
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());
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))
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);
// prevent building result of this task
this.generatedResult = null;
return true;
}
}

View File

@ -0,0 +1,29 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import ru.entaxy.platform.base.objects.EntaxyObject;
public interface ObjectDataResolver {
public String getSupportedObjectType();
public Object resolve(EntaxyObject sourceObject, String propertyName);
}

View File

@ -0,0 +1,84 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.HashMap;
import java.util.Map;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObjectService;
@Component(service = ObjectResolveHelper.class, immediate = true)
public class ObjectResolveHelper {
public static ObjectResolveHelper _INSTANCE;
public static ObjectResolveHelper getInstance(){
return _INSTANCE;
}
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyObjectService entaxyObjectService;
protected Map<String, ObjectDataResolver> externalResolvers = new HashMap<>();
DefaultObjectDataResolver defaultObjectDataResolver = new DefaultObjectDataResolver();
@Activate
public void activate() {
_INSTANCE = this;
}
@Reference(unbind = "removeResolver", cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY, collectionType = CollectionType.SERVICEOBJECTS, service = ObjectDataResolver.class)
public void addResolver(ObjectDataResolver resolver) {
synchronized (externalResolvers) {
externalResolvers.put(resolver.getSupportedObjectType(), resolver);
}
}
public void removeResolver(ObjectDataResolver resolver) {
synchronized (externalResolvers) {
externalResolvers.remove(resolver.getSupportedObjectType());
}
}
public EntaxyObject findObject(String objectId, String objectType) {
return entaxyObjectService.getObjects().stream()
.filter(obj -> (obj.getObjectId().equals(objectId) && obj.getObjectType().equals(objectType)))
.findFirst().orElse(null);
}
public ObjectDataResolver getResolver(EntaxyObject object) {
return externalResolvers.getOrDefault(object.getObjectType(), defaultObjectDataResolver);
}
public Object resolve(EntaxyObject entaxyObject, String propertyName) {
return getResolver(entaxyObject).resolve(entaxyObject, propertyName);
}
}

View File

@ -0,0 +1,67 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.Map;
import ru.entaxy.platform.base.objects.EntaxyObject;
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.FactoredObjectProxy;
public class ResolveObjectTask extends AbstractTask {
public FactoredObjectProxy origin;
public EntaxyObject targetObject;
public ResolveObjectTask(FactoredObjectProxy object) {
super();
this.origin = object;
}
@Override
public String getInfo() {
return "RESOLVE-OBJECT "
+ "["
+ origin.getObjectId()
+ " : "
+ origin.getObjectType()
+ "]";
// + objectRef.factoryId;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
String targetId = origin.getObjectId();
String targetType = origin.getObjectType();
this.targetObject = ObjectResolveHelper.getInstance().findObject(targetId, targetType);
if (this.targetObject == null) {
throw new IllegalArgumentException("Object not found: " + targetId + ":" + targetType);
}
return true;
}
}

View File

@ -0,0 +1,99 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
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.FactoredObjectRef;
public class ResolveRefTask extends AbstractRefTask {
protected ResolveRefTask(FactoredObjectRef objectRef) {
super(objectRef);
}
@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;
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 isFinal() {
return false;
}
}

View File

@ -0,0 +1,56 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergingMap.Mapping;
public abstract class AbstractMergeProcessor implements MergeProcessor {
protected Map<String, List<String>> mapping;
protected AbstractMergeProcessor() {
super();
mapping = new HashMap<>();
if (this.getClass().isAnnotationPresent(MergingMap.class)) {
MergingMap map = this.getClass().getAnnotation(MergingMap.class);
Mapping[] mappings = map.mappings();
if (mappings != null)
for (int i=0; i<mappings.length; i++) {
String source = mappings[i].source();
String[] targets = mappings[i].targets();
if ((targets == null) || (targets.length == 0))
continue;
this.mapping.put(source, Arrays.asList(targets));
}
}
}
@Override
public Map<String, List<String>> getMergingMap() {
return mapping;
}
}

View File

@ -0,0 +1,111 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.Map;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.support.xml.CommonXMLUtils;
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergingMap.Mapping;
@Component(service = MergeProcessor.class, immediate = true)
@MergingMap(mappings = {
@Mapping(source = Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT, targets = {Generated.GENERATED_TYPE_BLUEPRINT})
})
public class BlueprintMergeProcessor extends AbstractMergeProcessor {
private static final Logger log = LoggerFactory.getLogger(BlueprintMergeProcessor.class);
@Override
public Generated merge(Generated source, Generated target, Map<String, Object> config) {
NodeList sourceNodes = null;
if (source.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT)) {
String toParse = "<fragment>" + source.getObject().toString() + "</fragment>";
try {
Document sourceDoc = CommonXMLUtils.parseString(true, toParse);
sourceNodes = sourceDoc.getFirstChild().getChildNodes();
for (int i=0; i<sourceNodes.getLength(); i++) {
Node node = sourceNodes.item(i);
}
} catch (Exception e) {
log.error("Can't parse: \n" + toParse, e);
}
}
if ((sourceNodes == null) || (sourceNodes.getLength()==0))
return target;
Document targetDoc = null;
Node targetNode = null;
Node targetNodeBefore = null;
if (target.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT)) {
try {
targetDoc = CommonXMLUtils.parseString(true, target.getObject().toString());
targetNode = targetDoc.getFirstChild();
NodeList manifests = targetDoc.getElementsByTagName("manifest");
for (int i=0; i<manifests.getLength(); i++)
if ((manifests.item(i).getParentNode() != null) && (manifests.item(i).getParentNode() == targetNode)) {
targetNodeBefore = manifests.item(i).getNextSibling();
break;
}
} catch (Exception e) {
log.error("Can't parse: \n" + target.getObject().toString(), e);
}
}
if (targetNode == null)
return null;
if (targetNode.getChildNodes().getLength()==0)
for (int i=0; i<sourceNodes.getLength(); i++)
targetNode.appendChild(targetDoc.adoptNode(sourceNodes.item(i).cloneNode(true)));
else {
if (targetNodeBefore == null)
targetNodeBefore = targetNode.getFirstChild();
for (int i=0; i<sourceNodes.getLength(); i++)
targetNode.insertBefore(targetDoc.adoptNode(sourceNodes.item(i).cloneNode(true)), targetNodeBefore);
}
try {
String resultBlueprint = CommonXMLUtils.doc2string(targetDoc);
Generated result = Generated.create(Generated.GENERATED_TYPE_BLUEPRINT, resultBlueprint);
result.getProperties().putAll(target.getProperties());
return result;
} catch (Exception e) {
log.error("Can't convert to string", e);
}
return null;
}
}

View File

@ -0,0 +1,106 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
@Component(service = MergeHelper.class, immediate = true)
public class MergeHelper {
private static MergeHelper _INSTANCE = null;
public static MergeHelper getInstance() {
return _INSTANCE;
}
protected static class MergeProcessorWrapper {
MergeProcessor mergeProcessor;
public MergeProcessorWrapper(MergeProcessor mergeProcessor) {
this.mergeProcessor = mergeProcessor;
}
}
protected Map<MergeProcessor, MergeProcessorWrapper> wrappersMap = new HashMap<>();
protected Map<String, Map<String, MergeProcessorWrapper>> processors = new HashMap<>();
@Activate
public void activate(ComponentContext componentContext) {
_INSTANCE = this;
}
@Reference(unbind = "removeMergeProcessor", cardinality = ReferenceCardinality.MULTIPLE, collectionType = CollectionType.SERVICE
, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, service = MergeProcessor.class)
public void addMergeProcessor(MergeProcessor mergeProcessor) {
MergeProcessorWrapper wrapper = new MergeProcessorWrapper(mergeProcessor);
synchronized (this.wrappersMap) {
this.wrappersMap.put(mergeProcessor, wrapper);
}
Map<String, List<String>> mapping = mergeProcessor.getMergingMap();
synchronized (this.processors) {
for (Map.Entry<String, List<String>> entry: mapping.entrySet()) {
this.processors.putIfAbsent(entry.getKey(), new HashMap<>());
Map<String, MergeProcessorWrapper> map = this.processors.get(entry.getKey());
for (String target: entry.getValue())
map.put(target, wrapper);
}
}
}
public void removeMergeProcessor(MergeProcessor mergeProcessor) {
synchronized (wrappersMap) {
if (wrappersMap.containsKey(mergeProcessor)) {
wrappersMap.get(mergeProcessor).mergeProcessor = null;
wrappersMap.remove(mergeProcessor);
}
}
}
public boolean canMerge(String source, String target) {
return processors.containsKey(source)
&& processors.get(source).containsKey(target)
&& processors.get(source).get(target).mergeProcessor != null;
}
public Generated merge(Generated source, Generated target) {
if (!canMerge(source.getType(), target.getType()))
return null;
return processors.get(source.getType()).get(target.getType()).mergeProcessor.merge(source, target);
}
}

View File

@ -0,0 +1,38 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
public interface MergeProcessor {
Map<String, List<String>> getMergingMap();
default Generated merge(Generated source, Generated target) {
return this.merge(source, target, new HashMap<>());
};
Generated merge(Generated source, Generated target, Map<String, Object> config);
}

View File

@ -0,0 +1,39 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(TYPE)
public @interface MergingMap {
public @interface Mapping {
String source();
String[] targets();
}
Mapping[] mappings();
}

View File

@ -0,0 +1,96 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
public abstract class AbstractFactored extends AbstractItem {
private static final Logger log = LoggerFactory.getLogger(AbstractFactored.class);
public static boolean isFactored(JsonObject jsonObject) {
if (jsonObject.has(FIELDS.FACTORY_ID)) {
String factoryId = jsonObject.get(FIELDS.FACTORY_ID).getAsString();
return (factoryId != null) && !factoryId.isBlank();
}
return false;
}
public static AbstractFactored getContextOwner(Map<String, Object> context) {
initContext(context);
@SuppressWarnings("unchecked")
List<AbstractFactored> list = (List<AbstractFactored>)context.get(FACTORED_CONTEXT_KEY);
if (!list.isEmpty()) {
return list.get(list.size()-1);
}
return null;
}
public String factoryId;
public String scope = "public";
public String ownScope = "";
public List<AbstractItem> internalItems = new ArrayList<>();
protected AbstractFactored(ObjectModel objectModel) {
super(objectModel);
}
public void addInternal(AbstractItem item) {
if (!this.internalItems.contains(item))
this.internalItems.add(item);
}
public List<AbstractItem> getInternals(){
return this.internalItems;
}
protected void joinContext(Map<String, Object> context) {
initContext(context);
@SuppressWarnings("unchecked")
List<AbstractFactored> list = (List<AbstractFactored>)context.get(FACTORED_CONTEXT_KEY);
list.add(this);
}
protected void leaveContext(Map<String, Object> context) {
initContext(context);
@SuppressWarnings("unchecked")
List<AbstractFactored> list = (List<AbstractFactored>)context.get(FACTORED_CONTEXT_KEY);
list.remove(this);
}
public void wrap(JsonObject object, Map<String, Object> context, String path) {
super.wrap(object, context, path);
this.factoryId = object.has(FIELDS.FACTORY_ID)?object.get(FIELDS.FACTORY_ID).getAsString():null;
log.debug("WRAPPING FOR :: " + this.factoryId + "[" + jsonPath + "]");
}
}

View File

@ -0,0 +1,66 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.LinkedList;
import java.util.Map;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils.ObjectWrapper;
public abstract class AbstractItem extends ObjectWrapper {
public static final String FACTORED_CONTEXT_KEY = "factoredObjects";
public String jsonPath = "";
public String relativePath = "";
public JsonObject origin;
public FactoredObject definedIn = null;
protected ObjectModel objectModel;
protected AbstractItem(ObjectModel objectModel) {
this.objectModel = objectModel;
}
public boolean isDefinedIn(FactoredObject fo) {
if (fo == null)
return false;
FactoredObject test = this.definedIn;
while (test!=null && test!=fo)
test = test.definedIn;
return test == fo;
}
protected void computeRelativePath(String parentPath) {
this.relativePath = this.jsonPath.replace(parentPath, "");
if (this.relativePath.startsWith("."))
this.relativePath = this.relativePath.substring(1);
}
public static void initContext(Map<String, Object> context) {
if (!context.containsKey(FACTORED_CONTEXT_KEY))
context.put(FACTORED_CONTEXT_KEY, new LinkedList<>());
}
public void wrap(JsonObject object, Map<String, Object> context, String path) {
this.origin = object;
this.jsonPath = path;
}
}

View File

@ -0,0 +1,178 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils;
public class Calculation extends AbstractItem {
// TODO move const to EntaxyObject
public static final String FIELD_IS_CALCULATED = "isCalculated";
public static final Object NOT_ENOUGH_DATA = new Object();
public static boolean isCalculated(JsonObject jsonObject) {
if (!jsonObject.has(FIELD_IS_CALCULATED))
return false;
try {
return jsonObject.get(FIELD_IS_CALCULATED).getAsBoolean();
} catch (Exception e) {
return false;
}
}
protected ExpressionCalculation expressionCalculation;
public Calculation(ObjectModel objectModel) {
super(objectModel);
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
if (!ExpressionCalculation.isExpressionCalculation(object))
return;
super.wrap(object, context, path);
this.expressionCalculation = new ExpressionCalculation();
this.expressionCalculation.init(object);
AbstractFactored contextOwner = AbstractFactored.getContextOwner(context);
if (contextOwner instanceof FactoredObject)
this.definedIn = (FactoredObject)contextOwner;
contextOwner.addInternal(this);
computeRelativePath(contextOwner.jsonPath);
}
public Object calculate(ObjectModel objectModel, FactoredObject factoredObject) {
return this.expressionCalculation.calculate(objectModel, factoredObject);
}
public static class ExpressionCalculation {
// TODO move const to EntaxyObject
public static final String ATTR_EXPRESSION = "expression";
protected static final Object TOKEN_NOT_FOUND = new Object();
JsonObject jsonObject;
String expression;
List<String> toResolve = new ArrayList<>();
Map<String, Object> resolved = new HashMap<>();
public static boolean isExpressionCalculation(JsonObject jsonObject) {
return jsonObject.has(ATTR_EXPRESSION);
}
public void init(JsonObject jsonObject) {
this.jsonObject = jsonObject;
this.expression = jsonObject.get(ATTR_EXPRESSION).getAsString();
Pattern pattern = Pattern.compile("\\$\\{.+?\\}");
Matcher matcher = pattern.matcher(this.expression);
while (matcher.find()) {
String value = this.expression.substring(matcher.start(), matcher.end());
// System.out.println("\\nFOUND :: " + value);
this.toResolve.add(value.substring(2, value.length()-1));
}
}
public Object calculate(ObjectModel objectModel, FactoredObject factoredObject) {
for (String expr: toResolve) {
if (!resolved.containsKey(expr)) {
Object result = resolve(expr, objectModel, factoredObject);
if (!TOKEN_NOT_FOUND.equals(result)) {
resolved.put(expr, result);
}
}
}
toResolve.removeAll(resolved.keySet());
if (toResolve.isEmpty()) {
return doCalculate();
}
return NOT_ENOUGH_DATA;
}
public Object doCalculate() {
String result = expression;
for (Entry<String, Object> entry: resolved.entrySet()) {
Object value = entry.getValue();
String val = value==null?"":value.toString();
result = result.replace("${" + entry.getKey() + "}", val);
}
return result;
}
public Object resolve(String token, ObjectModel objectModel, FactoredObject factoredObject) {
JsonElement result = findElement(factoredObject.origin, token);
if (result == null)
return TOKEN_NOT_FOUND;
return JSONUtils.element2object(result);
}
public JsonElement findElement(JsonObject jsonObject, String pathFragment) {
JsonElement result = findElement(jsonObject, pathFragment, "");
return result;
}
public JsonElement findElement(JsonObject jsonObject, String pathFragment, String parentPath) {
for (Entry<String, JsonElement> entry: jsonObject.entrySet()) {
String currentPath = parentPath + "." + entry.getKey();
if (currentPath.endsWith(pathFragment))
return entry.getValue();
}
for (Entry<String, JsonElement> entry: jsonObject.entrySet()) {
if (!entry.getValue().isJsonObject())
continue;
String currentPath = parentPath + "." + entry.getKey();
JsonElement currentResult = findElement(entry.getValue().getAsJsonObject(), pathFragment, currentPath);
if (currentResult != null)
return currentResult;
}
return null;
}
}
}

View File

@ -0,0 +1,161 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
public class FactoredObject extends AbstractFactored {
private static final Logger log = LoggerFactory.getLogger(FactoredObject.class);
public static String EMBEDDED_FIELD = "##embedded";
public static String IS_EMBEDDED_FIELD = "isEmbedded";
public List<FactoredObject> dependsOn = new ArrayList<>();
public List<FactoredObject> dependants = new ArrayList<>();
public List<FactoredObjectRef> references = new ArrayList<>();
public List<AbstractFactored> embedded = new ArrayList<>();
protected String objectId = "";
protected String targetType = "";
protected String outputType = "";
protected boolean isEmbedded = false;
public FactoredObject (ObjectModel objectModel) {
super(objectModel);
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
super.wrap(object, context, path);
if (object.has(FIELDS.SCOPE)) {
this.ownScope = object.get(FIELDS.SCOPE).getAsString();
if (!this.ownScope.isEmpty())
this.scope = this.ownScope;
}
if (object.has(FIELDS.OBJECT_ID))
this.objectId = object.get(FIELDS.OBJECT_ID).getAsString();
else
this.setObjectId("TEMP-" + UUID.randomUUID().toString());
if (object.has(FIELDS.OBJECT_TYPE))
this.targetType = object.get(FIELDS.OBJECT_TYPE).getAsString();
if (object.has("outputType"))
this.outputType = object.get("outputType").getAsString();
if (object.has(IS_EMBEDDED_FIELD))
try{
this.isEmbedded = object.get(IS_EMBEDDED_FIELD).getAsBoolean();
} catch (Exception e) {
}
log.debug("\t CURRENT SCOPE :: " + this.scope);
initContext(context);
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;
fo.dependsOn(this);
this.definedIn = fo;
}
log.debug("\t EFFECTIVE SCOPE :: " + this.scope);
objectModel.addObject(this);
joinContext(context);
}
public String getObjectId() {
return objectId;
}
public void embed(AbstractFactored factored) {
this.embedded.add(factored);
this.embed(factored.origin);
}
protected void embed(JsonElement jsonElement) {
if (!this.origin.has(EMBEDDED_FIELD))
this.origin.add(EMBEDDED_FIELD, new JsonArray());
this.origin.get(EMBEDDED_FIELD).getAsJsonArray().add(jsonElement);
}
public void dependsOn(FactoredObject fo) {
this.dependsOn.add(fo);
fo.dependants.add(this);
}
@Override
public void setTraverseMap(Map<String, Object> traverseMap, Map<String, Object> context) {
super.setTraverseMap(traverseMap, context);
leaveContext(context);
}
public String getObjectType() {
return targetType;
}
public void setObjectType(String targetType) {
this.targetType = targetType;
this.origin.remove(FIELDS.OBJECT_TYPE);
this.origin.addProperty(FIELDS.OBJECT_TYPE, this.getObjectType());
}
public void setObjectId(String objectId) {
this.objectId = objectId;
this.origin.remove(FIELDS.OBJECT_ID);
this.origin.addProperty(FIELDS.OBJECT_ID, this.getObjectId());
}
public String getOutputType() {
return outputType;
}
public boolean isEmbedded() {
return isEmbedded;
}
public void setEmbedded(boolean isEmbedded) {
this.isEmbedded = isEmbedded;
this.origin.remove(IS_EMBEDDED_FIELD);
this.origin.addProperty(IS_EMBEDDED_FIELD, isEmbedded);
}
}

View File

@ -0,0 +1,69 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
public class FactoredObjectProxy extends FactoredObject {
private static final Logger log = LoggerFactory.getLogger(FactoredObjectProxy.class);
public static final String IS_PROXY_FIELD = "isProxy";
public static final String UNKNOWN_PROXIED_FACTORY_ID = "__##";
public static JsonObject getDefaultOrigin() {
JsonObject result = new JsonObject();
result.addProperty(FIELDS.FACTORY_ID, UNKNOWN_PROXIED_FACTORY_ID);
result.addProperty(IS_PROXY_FIELD, true);
return result;
}
public static boolean isProxy(JsonObject jsonObject) {
try {
if (!jsonObject.has(IS_PROXY_FIELD))
return false;
boolean isRef = jsonObject.get(IS_PROXY_FIELD).getAsBoolean();
return isRef;
} catch (Exception e) {
return false;
}
}
public FactoredObjectProxy(ObjectModel objectModel) {
super(objectModel);
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
super.wrap(object, context, path);
}
}

View File

@ -0,0 +1,254 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
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_TYPE_FIELD = "targetType";
public static String TARGET_VALUE_FIELD = "targetValue";
public static String IS_RESOLVED_FIELD = "isResolved";
public static String IS_LINK = "isLink";
protected FactoredObject targetObject = null;
protected String targetId = "";
protected String targetType = "";
protected boolean isExternal = true;
protected boolean isResolved = true;
protected boolean isBackRef = false;
protected boolean refByValueOnly = false;
protected boolean isLink = 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_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(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_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(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);
if (object.has(TARGET_ID_FIELD))
this.targetId = object.get(TARGET_ID_FIELD).getAsString();
if (object.has(TARGET_VALUE_FIELD))
this.targetId = 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(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) {
}
AbstractFactored contextOwner = getContextOwner(context);
if ((contextOwner != null) && (contextOwner instanceof FactoredObject)) {
FactoredObject fo = (FactoredObject)contextOwner;
log.debug("\t IN CONTEXT :: " + fo.factoryId + "[" + fo.jsonPath + "]");
computeRelativePath(fo.jsonPath);
if (null == this.ownScope || this.ownScope.isEmpty())
this.scope = fo.scope;
this.definedIn = fo;
}
objectModel.addRef(this);
}
public boolean isBackRef() {
return isBackRef;
}
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 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 isRefByValueOnly() {
return refByValueOnly;
}
public void setRefByValueOnly(boolean isRefByValueOnly) {
this.refByValueOnly = isRefByValueOnly;
}
public String getTargetId() {
if (targetObject == null)
return targetId;
return targetObject.getObjectId();
}
public String getTargetType() {
if (targetObject == null)
return targetType;
return 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.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

@ -0,0 +1,50 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.base.support.JSONUtils.ObjectWrapper;
public class FactoryChecker extends JSONUtils.ObjectChecker {
protected ObjectModel objectModel;
public FactoryChecker(ObjectModel objectModel) {
this.objectModel = objectModel;
}
@Override
public ObjectWrapper checkObject(JsonObject object) {
if (FactoredObjectRef.isRef(object))
return new FactoredObjectRef(objectModel);
if (FactoredObjectProxy.isProxy(object)) {
return new FactoredObjectProxy(objectModel);
}
if (!AbstractFactored.isFactored(object))
if (Calculation.isCalculated(object))
return new Calculation(objectModel);
else
return null;
return new FactoredObject(this.objectModel);
}
}

View File

@ -0,0 +1,281 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.objectmodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.DependencySorter;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.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();
List<FactoredObject> fos = this.objects.stream().filter(fo -> fo.getObjectId().equals(targetId))
.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());
return dependencies;
}
});
/* new LinkedList<>(rootObjects);
Collections.<FactoredObject>sort(sortedRootObjects, new Comparator<FactoredObject>() {
@Override
public int compare(FactoredObject o1, FactoredObject o2) {
if (o1.dependsOn.contains(o2))
return 1;
if (o2.dependsOn.contains(o1))
return -1;
return o1.dependsOn.size() - o2.dependsOn.size();
}
});
*/
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);
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);
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;
}
}

View File

@ -0,0 +1,33 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.support;
import java.util.Collections;
import org.apache.commons.collections4.list.AbstractLinkedList;
import ru.entaxy.platform.core.artifact.Artifact;
public class ArtifactList extends AbstractLinkedList<Artifact> {
public ArtifactList() {
super(Collections.emptyList());
}
}

View File

@ -0,0 +1,62 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.support;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import ru.entaxy.platform.core.artifact.service.ArtifactService;
@Component(immediate = true)
public class ArtifactsHelper {
protected static ArtifactsHelper instance = null;
public static ArtifactsHelper getInstance() {
return ArtifactsHelper.instance;
}
protected ArtifactService artifactService;
@Activate
public void activate(ComponentContext componentContext) {
// Artifacts.registerSupport(Blueprint.class);
ArtifactsHelper.instance = this;
}
public ArtifactService getArtifactService() {
return artifactService;
}
@Reference(unbind = "removeArtifactService", cardinality = ReferenceCardinality.MANDATORY, collectionType = CollectionType.SERVICE)
public void setArtifactService(ArtifactService artifactService) {
this.artifactService = artifactService;
}
public void removeArtifactService(ArtifactService artifactService) {
this.artifactService = null;
}
}

View File

@ -0,0 +1,34 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.support;
import java.util.Collections;
import org.apache.commons.collections4.list.AbstractLinkedList;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
public class DeployedArtifactList extends AbstractLinkedList<DeployedArtifact> {
public DeployedArtifactList() {
super(Collections.emptyList());
}
}

View File

@ -0,0 +1,34 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.executor.support;
import java.util.Collections;
import org.apache.commons.collections4.list.AbstractLinkedList;
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
public class InstallationResultList extends AbstractLinkedList<InstallationResult> {
public InstallationResultList() {
super(Collections.emptyList());
}
}

View File

@ -0,0 +1,75 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
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)
);
}
@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<>();
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

@ -0,0 +1,155 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
import ru.entaxy.platform.core.producer.wrapper.DefaultFactoryWrapper;
public abstract class DefaultProducer implements EntaxyProducer {
private static final Logger log = LoggerFactory.getLogger(DefaultProducer.class);
protected Class<? extends AbstractFactoryWrapper> factoryWrapperClass = DefaultFactoryWrapper.class;
protected Map<EntaxyFactory, AbstractFactoryWrapper> factories = new HashMap<>();
protected List<String> supportedTypes = new ArrayList<>();
protected List<EntaxyProducerListener> listeners = new ArrayList<>();
public DefaultProducer() {
if (this.getClass().isAnnotationPresent(EntaxyProducerInfo.class)) {
EntaxyProducerInfo info = this.getClass().getAnnotation(EntaxyProducerInfo.class);
this.supportedTypes = Arrays.asList(info.supportedTypes());
this.factoryWrapperClass = info.factoryWrapperClass();
}
}
@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 (this.getSupportedTypes().contains(factory.getFactoryType())) {
try {
AbstractFactoryWrapper wrapper = createWrapper(factory, wrapperClass);
addFields(wrapper);
factories.put(factory, wrapper);
synchronized (this.listeners) {
for (EntaxyProducerListener listener: this.listeners)
listener.factoryAdded(wrapper.getFactoryId(), wrapper.getFactoryType(), this);
}
log.debug("Factory added:" + factory.getFactoryId());
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.getFactoryId()
, factory.getFactoryType()
, getSupportedTypes().stream().collect(Collectors.joining(",")));
return null;
}
}
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 (this.getSupportedTypes().contains(factory.getFactoryType())) {
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.supportedTypes;
}
}

View File

@ -0,0 +1,38 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
import ru.entaxy.platform.core.producer.wrapper.DefaultFactoryWrapper;
@Retention(RUNTIME)
@Target(TYPE)
public @interface EntaxyProducerInfo {
String[] supportedTypes() default {};
Class<? extends AbstractFactoryWrapper> factoryWrapperClass() default DefaultFactoryWrapper.class;
}

View File

@ -0,0 +1,156 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducingCommandExecutor;
import ru.entaxy.platform.core.producer.executor.ProducingExecutor;
import ru.entaxy.platform.core.producer.executor.commands.Analyze;
import ru.entaxy.platform.core.producer.executor.commands.Build;
import ru.entaxy.platform.core.producer.executor.commands.Deploy;
import ru.entaxy.platform.core.producer.executor.commands.Enrich;
import ru.entaxy.platform.core.producer.executor.commands.Generate;
import ru.entaxy.platform.core.producer.executor.commands.Install;
import ru.entaxy.platform.core.producer.executor.commands.Layout;
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 {
private static final Logger log = LoggerFactory.getLogger(EntaxyProducerServiceImpl.class);
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));
}
@Override
public void registerCommand(ProducingCommandExecutor commandExecutor) {
this.commandExecutors.put(commandExecutor.getId(), commandExecutor);
}
@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, 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) {
for (EntaxyProducer p: producers)
if (p.getSupportedTypes().contains(type))
return p;
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;
}
}

View File

@ -0,0 +1,162 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public class FieldInfoImpl implements EntaxyFactory.FieldInfo {
JsonObject jsonOrigin = null;
String name = "";
String type = "";
String displayName = "";
String description = "";
boolean immutable = false;
boolean required = false;
Object defaultValue = "";
boolean conditional = false;
String condition = null;
boolean isRef = false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Object getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean isRequired) {
this.required = isRequired;
}
public boolean isImmutable() {
return immutable;
}
public void setImmutable(boolean isImmutable) {
this.immutable = isImmutable;
}
public FieldInfoImpl name(String nameValue) {
this.setName(nameValue);
return this;
};
public FieldInfoImpl displayName(String displayNameValue) {
this.setDisplayName(displayNameValue);
return this;
};
public FieldInfoImpl type(String typeValue) {
this.setType(typeValue);
return this;
};
public FieldInfoImpl defaultValue(String DefaultValueValue) {
this.setDefaultValue(DefaultValueValue);
return this;
};
public FieldInfoImpl description(String descriptionValue) {
this.setDescription(descriptionValue);
return this;
};
public FieldInfoImpl required(boolean requiredValue) {
this.setRequired(requiredValue);
return this;
};
public FieldInfoImpl immutable(boolean immutableValue) {
this.setImmutable(immutableValue);
return this;
}
public boolean isConditional() {
return conditional;
}
public void setConditional(boolean conditional) {
this.conditional = conditional;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public boolean isRef() {
return isRef;
}
public void setRef(boolean isRef) {
this.isRef = isRef;
}
public void setDefaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
}
@Override
public JsonObject getJsonOrigin() {
if (jsonOrigin == null) {
Gson gson = new Gson();
JsonElement result = gson.toJsonTree(this);
if (result.isJsonObject()) {
this.jsonOrigin = result.getAsJsonObject();
// remove origin itself
}
}
return this.jsonOrigin;
}
public void setJsonOrigin(JsonObject jsonOrigin) {
this.jsonOrigin = jsonOrigin;
};
}

View File

@ -0,0 +1,80 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.impl;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
public class RefFieldInfoImpl extends FieldInfoImpl implements EntaxyFactory.RefFieldInfo{
protected boolean isBackRef = false;
protected boolean isRefByValueOnly = false;
protected String refField = EntaxyObject.FIELDS.OBJECT_ID;
/* EntaxyFactory.RefFieldInfo */
@Override
public boolean isBackRef() {
return isBackRef;
}
@Override
public boolean isRefByValueOnly() {
return isRefByValueOnly;
}
@Override
public String getRefField() {
return refField;
}
/* builder */
public RefFieldInfoImpl backRef(boolean backRefValue) {
this.setBackRef(backRefValue);
return this;
};
public RefFieldInfoImpl refByValueOnly(boolean refByValueOnlyValue) {
this.setRefByValueOnly(refByValueOnlyValue);
return this;
};
public RefFieldInfoImpl refField(String refFieldValue) {
this.setRefField(refFieldValue);
return this;
};
/* others */
public void setBackRef(boolean isBackRef) {
this.isBackRef = isBackRef;
}
public void setRefByValueOnly(boolean isRefByValueOnly) {
this.isRefByValueOnly = isRefByValueOnly;
}
public void setRefField(String refField) {
this.refField = refField;
}
}

View File

@ -0,0 +1,59 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.wrapper;
import java.util.Map;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
public abstract class AbstractFactoryWrapper implements EntaxyWrappedFactory {
public static interface GenerationProcessor {
public default void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope
, String objectType, Map<String, Object> parameters) throws EntaxyFactoryException{
};
public default void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope
, String objectType, Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException{
};
}
protected GenerationProcessor generationProcessor = null;
public AbstractFactoryWrapper(EntaxyFactory origin) {
super();
}
public void setGenerationProcessor(GenerationProcessor generationProcessor) {
this.generationProcessor = generationProcessor;
}
public abstract void addField(FieldInfo fieldInfo);
public abstract void addField(String outputType, FieldInfo fieldInfo);
}

View File

@ -0,0 +1,266 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.wrapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.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;
}
@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 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();
}
@Override
public String getType() {
return origin.getType();
}
@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 {
ServiceReference<?>[] refs = bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.length));
if (refs == null)
return;
for (int i=0; i<refs.length; i++) {
try {
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(refs[i]);
processor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(refs[i]);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (InvalidSyntaxException 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 {
ServiceReference<?>[] refs = bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.length));
if (refs == null)
return;
for (int i=0; i<refs.length; i++) {
try {
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(refs[i]);
processor.postGenerate(this, outputType, scope, getFactoryType(), parameters, generated);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(refs[i]);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (InvalidSyntaxException e) {
log.error("Error getting services", e);
}
}
@Override
public EntaxyFactory getOrigin() {
return this.origin;
}
}

View File

@ -0,0 +1,94 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.wrapper;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.FieldInfo;
public class FieldWrapper implements FieldInfo {
protected FieldInfo origin;
public FieldWrapper(FieldInfo origin) {
this.origin = origin;
}
@Override
public String getName() {
return origin.getName();
}
@Override
public String getType() {
return origin.getType();
}
@Override
public String getDisplayName() {
return origin.getDisplayName();
}
@Override
public String getDescription() {
return origin.getDescription();
}
@Override
public boolean isImmutable() {
return origin.isImmutable();
}
@Override
public boolean isRequired() {
return origin.isRequired();
}
@Override
public Object getDefaultValue() {
return origin.getDefaultValue();
}
@Override
public boolean isConditional() {
return origin.isConditional();
}
@Override
public String getCondition() {
return origin.getCondition();
}
@Override
public boolean isRef() {
return origin.isRef();
}
@Override
public JsonObject getJsonOrigin() {
try {
return origin.getJsonOrigin().deepCopy();
} catch (Exception e) {
return new JsonObject();
}
}
}

View File

@ -0,0 +1,45 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.wrapper;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.RefFieldInfo;
public class RefFieldWrapper extends FieldWrapper implements RefFieldInfo {
public RefFieldWrapper(RefFieldInfo origin) {
super(origin);
}
@Override
public boolean isBackRef() {
return ((RefFieldInfo)origin).isBackRef();
}
@Override
public boolean isRefByValueOnly() {
return ((RefFieldInfo)origin).isRefByValueOnly();
}
@Override
public String getRefField() {
return ((RefFieldInfo)origin).getRefField();
}
}

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,46 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producing-config-support</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: CONFIG SUPPORT</name>
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: CONFIG SUPPORT</description>
<properties>
</properties>
<dependencies>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.core.object-producing
</groupId>
<artifactId>object-producer-core</artifactId>
<version>${project.version}</version>
<type>bundle</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<obrRepository>NONE</obrRepository>
<instructions>
<Entaxy-Factory-Provider>true</Entaxy-Factory-Provider>
<Entaxy-Template-Provider>true</Entaxy-Template-Provider>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,273 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
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.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.api.ProducingCommandExecutor;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
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;
import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@Component(service = ProducingCommandExecutor.class, immediate = true)
@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);
}
@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 {
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 Exception("Factory not found: [" + factoryId + "]");
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;
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;
if (!ObjectConfig.isConfigurable(entaxyFactory, EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT, refField))
// 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

@ -0,0 +1,76 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import org.osgi.service.component.annotations.Component;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.core.producer.executor.generationmodel.DefaultObjectDataResolver;
import ru.entaxy.platform.core.producer.executor.generationmodel.ObjectDataResolver;
@Component(service = ObjectDataResolver.class, immediate = true)
public class ConfigObjectDataResolver extends DefaultObjectDataResolver {
@Override
public String getSupportedObjectType() {
return ObjectConfig.CONFIG_OBJECT_TYPE;
}
@Override
protected Object resolveNotRoot(EntaxyObject sourceObject, String propertyName, JsonObject jsonRoot) {
/* System.out.println("\n\n\tRESOLVE - ConfigObjectDataResolver :: " + propertyName
+ "\n" + jsonRoot); */
if (jsonRoot.has(FIELDS.PROPERTIES)) {
JsonElement propertiesElement = jsonRoot.get(FIELDS.PROPERTIES);
if (propertiesElement.isJsonObject()) {
JsonObject properties = propertiesElement.getAsJsonObject();
/* System.out.println("\n\n\tCONFIGURED DATA:"
+ "\nconfigured: " + properties.get(ObjectConfig.CONFIG_ID_FIELD_NAME)
+ "\nconfiguredType: " + properties.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME)
+ "\nconfiguredProperties: " + properties.get(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME)
); */
if (properties.has(ObjectConfig.CONFIG_ID_FIELD_NAME)
&& properties.has(ObjectConfig.CONFIG_TYPE_FIELD_NAME)
&& properties.has(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME)) {
String targetId = properties.get(ObjectConfig.CONFIG_ID_FIELD_NAME).getAsString();
String targetType = properties.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).getAsString();
JsonElement configuredPropertiesElement = properties.get(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
if (configuredPropertiesElement.isJsonObject()) {
JsonObject configuredProperties = configuredPropertiesElement.getAsJsonObject();
String configPrefix = ObjectConfig.getConfigurationPrefix(targetId, targetType);
if (configuredProperties.has(propertyName))
return configPrefix + propertyName + "}";
}
}
}
}
return super.resolveNotRoot(sourceObject, propertyName, jsonRoot);
}
}

View File

@ -0,0 +1,87 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.Map;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
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.EntaxyFactoryException;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
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)
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;
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)parameters.get(EntaxyObject.FIELDS.PROPERTIES);
if (!properties.containsKey(ObjectConfig.CONFIG_FIELD_NAME))
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()))
continue;
properties.put(entry.getKey(), ObjectConfig.getConfigurationPrefix(objectId, objectType) + entry.getKey() + "}");
}
ObjectConfig.removeConfigData(parameters);
log.debug("preGenerate for {}:{}", wrappedFactory.getFactoryId(), wrappedFactory.getFactoryType());
}
@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

@ -0,0 +1,186 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
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;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedHeaders;
import ru.entaxy.platform.core.producer.impl.CommonObjectProducer;
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})
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);
// 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);
}
}
@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());
}
}
}

View File

@ -0,0 +1,146 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.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 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";
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) {
Optional<FieldInfo> fi = factory.getOutputByType(outputType).getFields().stream().filter(f -> f.getName().equals(fieldName)).findFirst();
if (!fi.isPresent())
return false;
if (!fi.get().getJsonOrigin().has(CONFIGURABLE_ATTRIBUTE_NAME))
return true;
try {
return fi.get().getJsonOrigin().get(CONFIGURABLE_ATTRIBUTE_NAME).getAsBoolean();
} catch (Exception e) {
return true;
}
}
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.info("\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;
}
if (field.isImmutable())
return immutables;
return configurables;
}
}

View File

@ -0,0 +1,66 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.Optional;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObjectService;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
@Component(service = ObjectConfigHelper.class, immediate = true)
public class ObjectConfigHelper {
private static ObjectConfigHelper _INSTANCE = null;
public static ObjectConfigHelper getInstance() {
return _INSTANCE;
}
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyObjectService entaxyObjectService;
public ObjectConfigHelper() {
super();
_INSTANCE = this;
}
public EntaxyObject findObject(String objectId, String objectType) {
Optional<EntaxyObject> object = entaxyObjectService.getObjects().stream()
.filter(obj -> (obj.getObjectId().equals(objectId) && obj.getObjectType().equals(objectType)))
.findFirst();
return object.orElse(null);
}
public boolean isDirectValueOnly(FactoredObjectRef ref) {
if (!ref.origin.has(ObjectConfig.DIRECT_VALUE_ONLY_ATTR_NAME))
return false;
try {
return ref.origin.get(ObjectConfig.DIRECT_VALUE_ONLY_ATTR_NAME).getAsBoolean();
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,37 @@
{
"factory": {
"id": "common-config",
"type": "entaxy.runtime.config",
"description": "Blueprint configuration factory"
},
"entaxy.runtime.config": {},
"fields": {
"configurables": {
"type": "Map",
"group": "config",
"required": true,
"defaultValue": {}
},
"immutables": {
"type": "Map",
"group": "config",
"required": true,
"defaultValue": {}
}
},
"outputs": {
"init": {
"isDefault": true,
"scopes": ["private"]
},
"config-field": {
"isDefault": false,
"generator": "",
"config": {},
"scopes": ["private"]
},
"ref":{
"scopes": ["private", "public"]
}
}
}

View File

@ -0,0 +1,47 @@
[#ftl attributes={"generated.type":"json"}]
[#--
~~~~~~licensing~~~~~~
object-producing-config-support
==========
Copyright (C) 2020 - 2021 EmDev LLC
==========
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
~~~~~~/licensing~~~~~~
--]
{
"factoryId": "common-config",
"scope": "private",
"properties": {
"configured": {
"factoryId": "[=targetObjectFactoryId]",
"type": "[=targetObjectType]",
"targetId": "[=targetObjectId]",
"isRef": true,
"isRefByValueOnly": true,
"refField": "objectId"
},
"configuredType":"[=targetObjectType]",
"configuredFactoryId":"[=targetObjectFactoryId]",
"configuredOutput":"[=targetObjectOutput]",
"configuredProperties": {
"factoryId": "[=targetObjectFactoryId]",
"type": "[=targetObjectType]",
"targetId": "[=targetObjectId]",
"isRef": true,
"isRefByValueOnly": true,
"refField": "properties"
}
}
}

View File

@ -0,0 +1,78 @@
[#ftl attributes={"generated.type":"blueprint.fragment"}]
[#--
~~~~~~licensing~~~~~~
object-producing-config-support
==========
Copyright (C) 2020 - 2021 EmDev LLC
==========
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
~~~~~~/licensing~~~~~~
--]
<!--
config for
objectId: [=configured]
type: [=configuredType]
pid: [=configurationPid]
prefix: [=placeholderPrefix]
configurables:
[#if configurables??]
[#list configurables as key, value]
[=key] = [#if value?is_boolean][=value?c][#else][=value][/#if]
[/#list]
[/#if]
immutables;
[#if immutables??]
[#list immutables as key, value]
[=key] = [=value]
[/#list]
[/#if]
-->
<bean id="[=configurationPid].defaults" class="ru.entaxy.platform.base.config.DefaultPropertiesProviderWithImmutables" activation="eager">
<argument index="0" type="java.lang.String" value="[=configured]"></argument>
<argument index="1" type="java.lang.String" value="[=configuredType]"></argument>
<argument index="2" type="java.lang.String" value="[=configurationPid]"></argument>
<argument index="3" type="org.osgi.framework.BundleContext" ref="blueprintBundleContext"></argument>
<argument index="4" type="java.util.Map">
<map key-type="java.lang.String" value-type="java.lang.Object">
[#if configurables??]
[#list configurables as key, value]
<entry key="[=key]" value="[#if value?is_boolean][=value?c][#else][=value][/#if]"></entry>
[/#list]
[/#if]
</map>
</argument>
[#if immutables??]
<argument index="5" type="java.util.Map">
<map key-type="java.lang.String" value-type="java.lang.Object">
[#list immutables as key, value]
<entry key="[=key]" value="[#if value?is_boolean][=value?c][#else][=value][/#if]"></entry>
[/#list]
</map>
</argument>
[/#if]
</bean>
<cm:property-placeholder persistent-id="[=configurationPid]" update-strategy="reload" id="[=configurationPid].placeholder"
placeholder-prefix="[=placeholderPrefix]" placeholder-suffix="}"
defaults-ref="[=configurationPid].defaults"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
</cm:property-placeholder>

View File

@ -0,0 +1,36 @@
[#ftl attributes={"generated.type":"blueprint.fragment"}]
[#--
~~~~~~licensing~~~~~~
object-producing-config-support
==========
Copyright (C) 2020 - 2021 EmDev LLC
==========
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
~~~~~~/licensing~~~~~~
--]
<!--
config ref for
objectId: [=configured]
type: [=configuredType]
pid: [=configurationPid]
prefix: [=placeholderPrefix]
-->
<cm:property-placeholder persistent-id="[=configurationPid]" update-strategy="reload" id="[=configurationPid].placeholder"
placeholder-prefix="[=placeholderPrefix]" placeholder-suffix="}"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
</cm:property-placeholder>

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,32 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producing-management</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: MANAGEMENT</name>
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: MANAGEMENT</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.core.producer.management*</bundle.osgi.export.pkg>
</properties>
<dependencies>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>management-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.core.object-producing
</groupId>
<artifactId>object-producer-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,39 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management;
import ru.entaxy.esb.platform.base.management.core.ManagementCore;
import ru.entaxy.esb.platform.base.management.core.Qualifier;
import ru.entaxy.esb.platform.base.management.core.api.MBeanAnnotated;
import ru.entaxy.esb.platform.base.management.core.api.MBeanExportPolicy;
@MBeanAnnotated(policy = MBeanExportPolicy.ANNOTATED_ONLY)
public interface FactoriesMBean {
public static final String FACTORIES_KEY = "category";
public static final String FACTORIES_KEY_VALUE = "factories";
public static final Qualifier Q_FACTORIES = ManagementCore.Q_PLATFORM
.qualifier(FactoriesMBean.FACTORIES_KEY, FactoriesMBean.FACTORIES_KEY_VALUE);
}

View File

@ -0,0 +1,56 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management;
import java.util.Map;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.TabularData;
import ru.entaxy.esb.platform.base.management.core.Qualifier;
import ru.entaxy.esb.platform.base.management.core.api.MBeanAnnotated;
import ru.entaxy.esb.platform.base.management.core.api.MBeanExportPolicy;
import ru.entaxy.esb.platform.base.management.core.api.Operation;
import ru.entaxy.esb.platform.base.management.core.api.Parameter;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
@MBeanAnnotated(policy = MBeanExportPolicy.ANNOTATED_ONLY)
public interface FactoryMBean {
public static final String FACTORY_KEY = "factoryId";
public static final String CATEGORY_KEY = "category";
public static Qualifier getQualifier(String factoryId, String factoryType) {
return ProducerMBean.getQualifier(factoryType).attribute(FACTORY_KEY, factoryId);
}
@Operation(desc = "Creates and installs a new object")
public TabularData createObject(
@Parameter(name = "objectId", desc = "ObjectId for new object, can be omitted in some cases")
String objectId,
@Parameter(name = "scope", desc = "Scope of the new object, 'public' by default")
String scope,
@Parameter(name = "properties", desc = "Properties of the new object in JSON format")
Map<String, Object> properties
) throws EntaxyFactoryException, OpenDataException;
@Operation(desc = "Get fields for creating a new object")
public String getFields(@Parameter(name = "outputType", desc = "Type of output") String outputType);
}

View File

@ -0,0 +1,35 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management;
import ru.entaxy.esb.platform.base.management.core.Qualifier;
import ru.entaxy.esb.platform.base.management.core.api.MBeanAnnotated;
import ru.entaxy.esb.platform.base.management.core.api.MBeanExportPolicy;
@MBeanAnnotated(policy = MBeanExportPolicy.ANNOTATED_ONLY)
public interface ProducerMBean {
public static final String PRODUCER_KEY = "producerType";
public static Qualifier getQualifier(String type) {
return FactoriesMBean.Q_FACTORIES.qualifier(PRODUCER_KEY, type);
}
}

View File

@ -0,0 +1,107 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.HashMap;
import java.util.Map;
import javax.management.DynamicMBean;
import javax.management.MBeanRegistration;
import javax.management.NotCompliantMBeanException;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.CollectionType;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.component.annotations.ServiceScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.base.management.core.ManagementCore;
import ru.entaxy.esb.platform.base.management.core.api.AnnotatedMBean;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.management.FactoriesMBean;
import ru.entaxy.platform.core.producer.management.ProducerMBean;
@Component(service = { FactoriesMBean.class, DynamicMBean.class, MBeanRegistration.class }, property = {
ManagementCore.JMX_OBJECTNAME + "=" + ManagementCore.Q_PLATFORM_S + "," + FactoriesMBean.FACTORIES_KEY + "="
+ FactoriesMBean.FACTORIES_KEY_VALUE }, scope = ServiceScope.SINGLETON, immediate = true)
public class FactoriesMBeanImpl extends AnnotatedMBean<FactoriesMBean> implements FactoriesMBean {
private static final Logger log = LoggerFactory.getLogger(FactoriesMBeanImpl.class);
protected Map<EntaxyProducer, ManagedTypedProducers> producersMap = new HashMap<>();
protected BundleContext bundleContext;
protected TypedProducerListener producerListener = null;
// to ensure FactoryMBeanPublisher is started
@Reference(cardinality = ReferenceCardinality.MANDATORY)
FactoryMBeanPublisher factoryMBeanPublisher;
@Activate
public FactoriesMBeanImpl(BundleContext bundleContext) throws NotCompliantMBeanException {
super(FactoriesMBean.class);
this.bundleContext = bundleContext;
log.debug("\n\tCONSTRUCTOR, bundleContext: [{}]\n"
, this.bundleContext==null?"null":this.bundleContext.getBundle().getBundleId());
this.producerListener = new TypedProducerListener(bundleContext, ProducerMBean.class);
}
@Reference(bind="bindProducer", unbind = "unbindProducer", cardinality = ReferenceCardinality.MULTIPLE
, policy = ReferencePolicy.DYNAMIC
, policyOption = ReferencePolicyOption.GREEDY, collectionType = CollectionType.SERVICE
, service = EntaxyProducer.class)
public void bindProducer(EntaxyProducer producer) {
log.debug("\n\tBinding producer: [{}]\n", producer.getProducerId());
synchronized (producersMap) {
if (producersMap.containsKey(producer)) {
producerListener.removed(producersMap.get(producer));
}
ManagedTypedProducers mtp = new ManagedTypedProducers(producer);
producersMap.put(producer, mtp);
if (producerListener != null)
producerListener.added(mtp);
}
}
public void unbindProducer(EntaxyProducer producer) {
synchronized (producersMap) {
if (producersMap.containsKey(producer)) {
if (producerListener != null)
producerListener.removed(producersMap.get(producer));
producersMap.remove(producer);
}
}
}
public void bindFactory(EntaxyFactory entaxyFactory) {
}
}

View File

@ -0,0 +1,130 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.base.management.core.api.AnnotatedMBean;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.SCOPE;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.base.support.CommonUtils;
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.management.FactoryMBean;
public class FactoryMBeanImpl extends AnnotatedMBean<FactoryMBean> implements FactoryMBean {
private static final Logger log = LoggerFactory.getLogger(FactoryMBeanImpl.class);
protected EntaxyFactory entaxyFactory;
public FactoryMBeanImpl(EntaxyFactory entaxyFactory) throws NotCompliantMBeanException {
super(FactoryMBean.class);
this.entaxyFactory = entaxyFactory;
}
@Override
public TabularData createObject(String objectId, String scope, Map<String, Object> properties) throws EntaxyFactoryException, OpenDataException {
log.debug("\n\tCREATE OBJECT with \nid: [{}] \nscope: [{}] \nproperties: [{}]"
, CommonUtils.getValid(objectId, "null")
, CommonUtils.getValid(scope, SCOPE.PUBLIC.label)
, properties==null?"{}":properties.toString());
EntaxyProducerService producerService = ProducerServiceHelper.getInstance().producerService;
String targetScope = CommonUtils.getValid(scope, SCOPE.PUBLIC.label);
if (SCOPE.valueOfLabel(targetScope)==null)
targetScope = SCOPE.PUBLIC.label;
JsonObject configuration = new JsonObject();
if (CommonUtils.isValid(objectId))
configuration.addProperty(EntaxyObject.FIELDS.OBJECT_ID, objectId);
configuration.addProperty(EntaxyObject.FIELDS.FACTORY_ID, this.entaxyFactory.getFactoryId());
configuration.addProperty(EntaxyObject.FIELDS.OBJECT_TYPE, this.entaxyFactory.getFactoryType());
configuration.addProperty(EntaxyObject.FIELDS.SCOPE, targetScope);
JsonElement propertiesValue = (new Gson()).toJsonTree(properties);
configuration.add(EntaxyObject.FIELDS.PROPERTIES, propertiesValue);
ProducerResult result = producerService.produce(configuration, "{\"install\": {}, \"store\":{}}");
CompositeType compositeType = new CompositeType(
"CommandResult"
, "CommandResult"
, new String[] {"Step", "Step name", "Step result"}
, new String[] {"Step", "Step name", "Step result"}
, new OpenType[] {SimpleType.INTEGER, SimpleType.STRING, SimpleType.STRING});
TabularType tabularType = new TabularType("ProducerResult"
, "ProducerResult"
, compositeType
, new String[] {"Step"});
TabularDataSupport dataSupport = new TabularDataSupport(tabularType);
int number = 0;
for (CommandResult cr: result.getCommandResults()) {
Map<String, Object> data = new HashMap<>();
data.put("Step", number++);
data.put("Step name", cr.commandId);
data.put("Step result", cr.result?"OK":"Failed");
CompositeDataSupport cds = new CompositeDataSupport(compositeType, data);
dataSupport.put(cds);
}
return dataSupport;
}
@Override
public String getFields(String outputType) {
return entaxyFactory.getFields(outputType)
.stream().map(fieldInfo -> {
JsonObject json = fieldInfo.getJsonOrigin();
if (!json.has("name")) {
json.addProperty("name", fieldInfo.getName());
}
return json;
}).collect(Collectors.toList()).toString();
}
}

View File

@ -0,0 +1,78 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import ru.entaxy.esb.platform.base.management.core.ManagementCore;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.producer.management.FactoryMBean;
@Component(service = FactoryMBeanPublisher.class, immediate = true)
public class FactoryMBeanPublisher {
protected static FactoryMBeanPublisher _INSTANCE = null;
public static FactoryMBeanPublisher getInstance() {
return _INSTANCE;
};
protected BundleContext bundleContext;
@Activate
public void activate(ComponentContext componentContext) {
this.bundleContext = componentContext.getBundleContext();
_INSTANCE = this;
}
public List<ServiceRegistration<FactoryMBean>> publish(FactoryMBeanImpl service, EntaxyFactory factory){
List<ServiceRegistration<FactoryMBean>> result = new ArrayList<>();
Hashtable<String, String> props = new Hashtable<>();
props.put(ManagementCore.JMX_OBJECTNAME
, FactoryMBean.getQualifier(factory.getId(), factory.getType()).getValue());
result.add(this.bundleContext.registerService(FactoryMBean.class, service, props));
if (CommonUtils.isValid(factory.getCategory())) {
props.put(ManagementCore.JMX_OBJECTNAME
, ManagementCore.Q_PLATFORM
.qualifier(FactoryMBean.CATEGORY_KEY, factory.getCategory())
.qualifier(FactoryMBean.FACTORY_KEY, factory.getId()).getValue());
result.add(this.bundleContext.registerService(FactoryMBean.class, service, props));
}
return result;
}
}

View File

@ -0,0 +1,34 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
public class ManagedTypedProducer {
String supportedType;
EntaxyProducer producer;
public ManagedTypedProducer(String suportedType, EntaxyProducer producer) {
this.supportedType = suportedType;
this.producer = producer;
}
}

View File

@ -0,0 +1,40 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.ArrayList;
import java.util.List;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
public class ManagedTypedProducers {
protected List<ManagedTypedProducer> producers = new ArrayList<>();
public ManagedTypedProducers(EntaxyProducer entaxyProducer) {
for (String type: entaxyProducer.getSupportedTypes())
producers.add(new ManagedTypedProducer(type, entaxyProducer));
}
public List<ManagedTypedProducer> getProducers() {
return producers;
}
}

View File

@ -0,0 +1,124 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.management.NotCompliantMBeanException;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.base.management.core.ManagementCore;
import ru.entaxy.esb.platform.base.management.core.api.AnnotatedMBean;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.management.FactoryMBean;
import ru.entaxy.platform.core.producer.management.ProducerMBean;
public class ProducerMBeanImpl extends AnnotatedMBean<ProducerMBean>
implements ProducerMBean, EntaxyProducer.EntaxyProducerListener {
private static final Logger log = LoggerFactory.getLogger(ProducerMBeanImpl.class);
protected BundleContext bundleContext;
protected String managedType;
protected EntaxyProducer entaxyProducer;
protected Map<String, List<ServiceRegistration<FactoryMBean>>> services = new HashMap<>();
protected Map<String, FactoryMBeanImpl> mbeans = new HashMap<>();
public ProducerMBeanImpl(BundleContext bundleContext, String managedType, EntaxyProducer entaxyProducer) throws NotCompliantMBeanException {
super(ProducerMBean.class);
this.bundleContext = bundleContext;
this.managedType = managedType;
this.entaxyProducer = entaxyProducer;
this.entaxyProducer.addListener(this);
synchronized (this.services) {
for(EntaxyFactory factory: this.entaxyProducer.getFactoriesForType(this.managedType))
registerFactory(factory);
}
}
@Override
public void factoryAdded(String factoryId, String factoryType, EntaxyProducer producer) {
if (!this.managedType.equals(factoryType))
return;
factoryRemoved(factoryId, factoryType, producer);
synchronized (this.services) {
registerFactory(this.entaxyProducer.getFactoryById(factoryId));
}
}
@Override
public void factoryRemoved(String factoryId, String factoryType, EntaxyProducer producer) {
if (!this.managedType.equals(factoryType))
return;
synchronized (this.services) {
if (this.services.containsKey(factoryId)) {
for (ServiceRegistration<FactoryMBean> sr: this.services.get(factoryId))
try {
sr.unregister();
} catch (Exception e) {
}
this.services.remove(factoryId);
this.mbeans.remove(factoryId);
}
}
}
protected void registerFactory(EntaxyFactory factory) {
try {
FactoryMBeanImpl impl = new FactoryMBeanImpl(factory);
Hashtable<String, String> props = new Hashtable<>();
props.put(ManagementCore.JMX_OBJECTNAME
, FactoryMBean.getQualifier(factory.getFactoryId(), factory.getFactoryType()).getValue());
this.services.put(factory.getId()
, FactoryMBeanPublisher.getInstance().publish(impl, factory));
this.mbeans.put(factory.getId(), impl);
} catch (NotCompliantMBeanException e) {
log.error("Error creating FactoryMBeanImpl", e);
}
}
public void beforeRemove() {
synchronized (services) {
for (List<ServiceRegistration<FactoryMBean>> lsr: services.values())
for (ServiceRegistration<FactoryMBean> sr: lsr)
try {
sr.unregister();
} catch (Exception e) {
}
services.clear();
mbeans.clear();
}
}
}

View File

@ -0,0 +1,45 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
@Component(service = ProducerServiceHelper.class, immediate = true)
public class ProducerServiceHelper {
private static ProducerServiceHelper _instance;
public static ProducerServiceHelper getInstance() {
return _instance;
}
@Reference (cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService producerService;
@Activate
public void activate() {
ProducerServiceHelper._instance = this;
}
}

View File

@ -0,0 +1,77 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-management
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.management.impl;
import java.util.Iterator;
import javax.management.NotCompliantMBeanException;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.base.management.core.utils.ManagedObjectsListener;
import ru.entaxy.platform.core.producer.management.ProducerMBean;
public class TypedProducerListener extends ManagedObjectsListener<ManagedTypedProducers, ManagedTypedProducer, ProducerMBean, ProducerMBeanImpl> {
private static final Logger log = LoggerFactory.getLogger(TypedProducerListener.class);
public TypedProducerListener(BundleContext bundleContext, Class<ProducerMBean> serviceClass) {
super(bundleContext, serviceClass);
}
@Override
protected Iterator<ManagedTypedProducer> getIterator(ManagedTypedProducers managedObject) {
return managedObject.getProducers().iterator();
}
@Override
protected String getKeyValue(ManagedTypedProducer object) {
return object.supportedType;
}
@Override
protected ProducerMBeanImpl createService(ManagedTypedProducer managedObject) {
try {
return new ProducerMBeanImpl(this.bundleContext, managedObject.supportedType, managedObject.producer);
} catch (NotCompliantMBeanException e) {
log.error("Error creating ProducerMBeanImpl: ", e);
return null;
}
}
@Override
protected String getJmxObjectName(ManagedTypedProducer managedObject) {
return ProducerMBean.getQualifier(managedObject.supportedType).getValue();
}
@Override
public void removed(ManagedTypedProducers managedObject) {
for (ManagedTypedProducer mtp: managedObject.getProducers()) {
getManaged()
.get(getKeyValue(mtp))
.service
.beforeRemove();
}
super.removed(managedObject);
}
}

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,35 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.8.2</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producing-shell</artifactId>
<packaging>bundle</packaging>
<name>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: SHELL</name>
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: SHELL</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.core.producer.shell*</bundle.osgi.export.pkg>
<bundle.osgi.remove.headers>none</bundle.osgi.remove.headers>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.core</artifactId>
<version>${karaf.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.core.object-producing
</groupId>
<artifactId>object-producer-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
public class EntaxyProducerServiceSupport {
public static final String SCOPE = "producer";
@Reference
EntaxyProducerService producerService;
}

View File

@ -0,0 +1,64 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
import ru.entaxy.platform.core.producer.shell.completers.FactoryIdCompleter;
public abstract class FactoryAwareCommand extends EntaxyProducerServiceSupport implements Action {
@Argument (index = 0, name = "factoryId", required = true)
@Completion(caseSensitive = false, value = FactoryIdCompleter.class)
String factoryId;
@Option(name = "-r", aliases = {"--use-origin"}, multiValued = false, required = false)
boolean useOrigin;
protected EntaxyFactory entaxyFactory;
@Override
public final Object execute() throws Exception {
for (EntaxyProducer p: producerService.getAllProducers()) {
entaxyFactory = p.getFactoryById(factoryId);
if (entaxyFactory != null)
break;
}
if (entaxyFactory == null)
System.out.println("Factory [" + factoryId + "] not found");
else {
if (useOrigin)
if (entaxyFactory instanceof EntaxyWrappedFactory)
entaxyFactory = ((EntaxyWrappedFactory)entaxyFactory).getOrigin();
return doExecute();
}
return null;
}
protected abstract Object doExecute() throws Exception;
}

View File

@ -0,0 +1,90 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import java.util.List;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.support.table.ShellTable;
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.RefFieldInfo;
import ru.entaxy.platform.base.support.CommonUtils;
@Service
@Command(scope = EntaxyProducerServiceSupport.SCOPE, name = "factory-fields")
public class FactoryFields extends FactoryAwareCommand {
@Option(name = "-o", aliases = {"--output"}, required = false)
String outputType;
@Override
protected Object doExecute() throws Exception {
ShellTable table = new ShellTable();
table.column("Name");
table.column("Type");
table.column("DisplayName");
table.column("DefaultValue").maxSize(50).wrap(false);
table.column("Required");
table.column("Immutable");
table.column("Is ref");
table.column("Is back ref");
table.column("Is ref by value");
List<FieldInfo> fields;
if (CommonUtils.isValid(outputType)) {
System.out.println("FOR outputType = " + outputType);
fields = entaxyFactory.getFields(outputType);
} else {
System.out.println("FOR default outputType = ");
fields = entaxyFactory.getFields();
}
for (EntaxyFactory.FieldInfo fi: fields)
table.addRow().addContent(
fi.getName(),
fi.getType(),
fi.getDisplayName(),
fi.getDefaultValue(),
(fi.isRequired()?"*":""),
(fi.isImmutable()?"*":""),
(fi.isRef()?"*":""),
(fi.isRef()
?(((RefFieldInfo)fi).isBackRef()
?"*"
:"")
:""),
(fi.isRef()
?(((RefFieldInfo)fi).isRefByValueOnly()
?"*"
:"")
:"")
);
table.print(System.out);
return null;
}
}

View File

@ -0,0 +1,80 @@
/*-
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2022 EmDev LLC
* ==========
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.shell;
import java.util.Map;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
@Service
@Command (scope = EntaxyProducerServiceSupport.SCOPE, name = "factory-generate")
public class FactoryGenerate extends FactoryAwareCommand implements Action {
@Option(name = "-ot", aliases = {"--outputType"}, multiValued = false, required = false)
String outputType;
@Option(name = "-s", aliases = {"--scope"}, multiValued = false, required = false)
String scope;
@Argument(index = 1, name = "properties", required = false)
String properties;
@Override
protected Object doExecute() throws Exception {
if (!CommonUtils.isValid(properties))
this.properties = "{}";
JsonElement je = (new JsonParser()).parse(properties);
Map<String, Object> propertiesMap = JSONUtils.element2map(je);
Generated result = null;
if (!CommonUtils.isValid(outputType))
result = entaxyFactory.generate(propertiesMap);
else if (!CommonUtils.isValid(scope))
result = entaxyFactory.generate(outputType, propertiesMap);
else
result = entaxyFactory.generate(outputType, scope, propertiesMap);
if (result == null)
System.out.println("NOTHING GENERATED");
else {
System.out.println("GENERATED :: [" + result.getType() + "]");
System.out.println("===");
System.out.println(result.getObject()==null?"->nothing":result.getObject().toString());
System.out.println("===");
}
return null;
}
}

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