clean project

This commit is contained in:
Ralph Soika 2026-06-23 13:22:44 +02:00
parent 18199c8f8f
commit 8ced4940b7
66 changed files with 0 additions and 13930 deletions

View file

@ -1,130 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs.cognition;
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_DEADLOCK;
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_ENABLED;
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_INITIALDELAY;
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_INTERVAL;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.imixs.workflow.engine.AsyncEventService;
import org.imixs.workflow.engine.EventLogService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.annotation.security.DeclareRoles;
import jakarta.annotation.security.RunAs;
import jakarta.ejb.Singleton;
import jakarta.ejb.Startup;
import jakarta.ejb.Timeout;
import jakarta.ejb.Timer;
import jakarta.ejb.TimerConfig;
import jakarta.ejb.TimerService;
import jakarta.inject.Inject;
/**
* The CognitoEventScheduler starts a scheduler service to process cognition
* events in an asynchronous way by calling the CognitoEventService.
* <p>
* The Scheduler runs on a non-persistent ejb timer with the same interval
* settings as the AsyncEventProcessor
* <p>
* Configuration is read from the environment variables
* 'ASYNCEVENT_PROCESSOR_INTERVAL' and an optional delay defined by
* 'ASYNCEVENT_PROCESSOR_INITIALDELAY'. To enable the processor
* 'ASYNCEVENT_PROCESSOR_ENABLED' must be set to true (default=false).
* 'ASYNCEVENT_PROCESSOR_DEADLOCK' deadlock timeout
* <p>
* In a clustered environment this timer runs in each cluster member that
* contains the EJB. So this means the non-persistent EJB Timer scales
* horizontal within a clustered environment – e.g. a Kubernetes cluster.
*
* @see AsyncEventService
* @version 1.1
* @author rsoika
*
*/
@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
@Startup
@Singleton
public class CognitoEventScheduler {
// enabled
@Inject
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_ENABLED, defaultValue = "false")
boolean enabled;
// timeout interval in ms
@Inject
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_INTERVAL, defaultValue = "1000")
long interval;
// initial delay in ms
@Inject
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_INITIALDELAY, defaultValue = "0")
long initialDelay;
// deadlock timeout interval in ms
@Inject
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_DEADLOCK, defaultValue = "60000")
long deadLockInterval;
private static final Logger logger = Logger.getLogger(CognitoEventScheduler.class.getName());
@Resource
TimerService timerService;
@Inject
CognitoEventService cognitoEventService;
@Inject
EventLogService eventLogService;
@PostConstruct
public void init() {
if (enabled) {
// Registering a non-persistent Timer Service.
final TimerConfig timerConfig = new TimerConfig();
timerConfig.setInfo("Dynamixs AI CognitoEventScheduler");
timerConfig.setPersistent(false);
timerService.createIntervalTimer(initialDelay, interval, timerConfig);
logger.log(Level.INFO, "├── ✅ Started CognitoEventScheduler - initalDelay={0} inverval={1}",
new Object[] { initialDelay, interval });
}
}
/**
* The method delegates the event processing to the stateless ejb
* AsyncEventProcessor.
* <p>
* Before processing the eventLog the method releases possible dead locks first.
* Both methods are running in separate transactions
*
*/
@Timeout
public void run(Timer timer) {
eventLogService.releaseDeadLocks(deadLockInterval,
CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT,
CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE);
cognitoEventService.processEventLog();
}
}

View file

@ -1,243 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs.cognition;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.imixs.ai.ImixsAIContextHandler;
import org.imixs.ai.workflow.OpenAIAPIConnector;
import org.imixs.ai.workflow.OpenAIAPIService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.AsyncEventScheduler;
import org.imixs.workflow.engine.EventLogService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.engine.jpa.EventLog;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import jakarta.annotation.security.DeclareRoles;
import jakarta.annotation.security.RunAs;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.ejb.TransactionAttribute;
import jakarta.ejb.TransactionAttributeType;
import jakarta.inject.Inject;
import jakarta.persistence.OptimisticLockException;
/**
* The CognitoEventService is responsible to process Dynamixs-AI Cognito events
* in an asynchronous batch process. The CognitoEventService automatically
* lookup eventLog entries of the topic "rag.event.*". The RAGEventService is
* called only by the RAGEventScheduler which is implementing a
* ManagedScheduledExecutorService.
* <p>
* The CognitoEventService reacts on events from the following types:
* <ul>
* <li>cognito.event.prompt - resoles the llm prompt based on the given workitem
* and creates a cache event</li>
* <li>cognito.event.cache - indicates that this entry is still cached in the
* event log database</li>
* </ul>
* The processor look up the workItem by the $uniqueId.
* <p>
* To prevent concurrent processes to handle the same workitems the batch
* process uses a Optimistic lock strategy. After fetching new event log entries
* the processor updates the eventLog entry in a new transaction and set the
* topic to 'batch.process.lock'. After that update we can be sure that no other
* process is dealing with these entries. After completing the processing step
* the eventlog entry will be removed.
* <p>
* To avoid ad deadlock the processor set an expiration time on the lock, so the
* lock will be auto-released after 1 minute (batch.processor.deadlock).
*
* @see AsyncEventScheduler
* @version 1.0
* @author rsoika
*
*/
@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
@Stateless
@LocalBean
public class CognitoEventService {
public static final String EVENTLOG_TOPIC_COGNITO_PROMPT = "cognito.event.prompt";
public static final String EVENTLOG_TOPIC_COGNITO_CACHE = "cognito.event.cache";
public static final String ITEM_PROMPT_DEFINITION = "prompt.definition";
private static final Logger logger = Logger.getLogger(CognitoEventService.class.getName());
@Inject
EventLogService eventLogService;
@Inject
private WorkflowService workflowService;
@Inject
private OpenAIAPIService llmService;
@Inject
ImixsAIContextHandler imixsAIContextHandler;
@Inject
CognitoLockHandler cognitoLockHandler;
@Inject
@ConfigProperty(name = OpenAIAPIConnector.ENV_LLM_SERVICE_ENDPOINT)
Optional<String> serviceEndpoint;
/**
* The method lookups for cognito prompt event log entries and updates the ....
* information
* <p>
* Each eventLogEntry provides optional a prompt template
*
*/
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public void processEventLog() {
long l = System.currentTimeMillis();
// test for new event log entries by timeout...
List<EventLog> events = eventLogService.findEventsByTimeout(100,
CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT, CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE);
if (events.size() > 0) {
logger.log(Level.INFO, "├── 🔃 processing {0} Cognito events....", events.size());
// do we know the endpoint?
if (!serviceEndpoint.isPresent()) {
logger.log(Level.WARNING,
"├── ⚠️ Missing environment var 'llm.service.endpoint' - can not process cognito events!");
return;
}
for (EventLog eventLogEntry : events) {
try {
boolean llmAPIDebug = true;
logger.log(Level.INFO,
"│ ├── Event: " + eventLogEntry.getTopic() + " - " + eventLogEntry.getRef());
// first try to lock the eventLog entry....
if (eventLogService.lock(eventLogEntry)) {
// Index / Update event?
ItemCollection workitem = workflowService.getWorkItem(eventLogEntry.getRef());
if (workitem == null) {
logger.log(Level.WARNING, "│ ├── ⚠️ unable to read workitem: " + eventLogEntry.getRef());
eventLogService.removeEvent(eventLogEntry.getId());
continue;
}
ItemCollection promptItemCol = new ItemCollection(eventLogEntry.getData());
switch (eventLogEntry.getTopic()) {
case CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT + ".lock":
// load the promptDefinition from the event data object
String promptTemplate = promptItemCol.getItemValueString(ITEM_PROMPT_DEFINITION);
imixsAIContextHandler.setWorkItem(workitem);
imixsAIContextHandler.addPromptDefinition(promptTemplate);
String llmPrompt = imixsAIContextHandler.toString();
// if we have a prompt we call the llm api endpoint
if (llmPrompt != null && !llmPrompt.isBlank()) {
String llmAPIEndpoint = serviceEndpoint.get();
// postPromptCompletion
// JsonObject jsonPrompt =
// llmService.buildJsonPromptObjectV1(imixsAIContextHandler);
String completionResult = llmService.postPromptCompletion(imixsAIContextHandler,
llmAPIEndpoint);
// process the ai.result....
if (llmAPIDebug) {
logger.info("===> Completion Result: ");
logger.info(completionResult);
}
String resultMessage = llmService.processPromptResult(completionResult, "", workitem);
// if the workitem is not locked we can safety update the $workflowabstarct
if (!cognitoLockHandler.isLocked(workitem.getUniqueID())) {
logger.log(Level.INFO,
"│ ├── ✓ workitem not locked - updating $workflowabstract...");
workitem.setItemValue("$workflowabstract", resultMessage);
workflowService.getDocumentService().save(workitem);
} else {
// workitem is still in edit mode - so we create a cache event that just stores
// the result. This is an async caching mechanism for the front end.
logger.log(Level.INFO,
"│ ├── ⚐ workitem locked - create COGNITO_CACHE event...");
promptItemCol.setItemValue("$workflowabstract", resultMessage);
// create a new event
eventLogService.createEvent(CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE,
workitem.getUniqueID(),
promptItemCol);
}
} else {
logger.finest(
"......no prompt definition found for " + workitem.getUniqueID());
}
// finally remove the event log entry...
eventLogService.removeEvent(eventLogEntry.getId());
break;
case CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE + ".lock":
logger.log(Level.INFO,
"│ ├── process COGNITO_CACHE event...");
if (!cognitoLockHandler.isLocked(workitem.getUniqueID())) {
logger.log(Level.INFO,
"│ ├── ✓ workitem not locked - updating $workflowabstract...");
// ItemCollection promptItemCol = new ItemCollection(eventLogEntry.getData());
String resultMessage = promptItemCol.getItemValueString("$workflowabstract");
workitem.setItemValue("$workflowabstract", resultMessage);
workflowService.getDocumentService().save(workitem);
// finally remove the event log entry...
eventLogService.removeEvent(eventLogEntry.getId());
} else {
// repeat event until workitem is unlocked
eventLogService.unlock((eventLogEntry));
}
break;
default:
// no op
}
}
} catch (OptimisticLockException e) {
// lock was not possible - continue....
logger.log(Level.INFO, "│ ├── ⚠️ unable to lock AsyncEvent: {0}", e.getMessage());
} catch (PluginException | AdapterException e) {
logger.log(Level.WARNING, e.getErrorCode() + " - " + e.getMessage());
// remove the event log entry...
eventLogService.removeEvent(eventLogEntry.getId());
}
}
logger.log(Level.INFO, "├── ✅ {0} CognitoEvents processed in {1}ms",
new Object[] { events.size(), System.currentTimeMillis() - l });
}
}
}

View file

@ -1,274 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
* https://www.imixs.com
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs.cognition;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.faces.data.WorkflowEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.interceptor.Interceptor;
/**
* The CognitoLockHandler is an application scoped CDI bean that holds a list of
* workitem uniqueIds currently in edit mode. This caching mechanism is used by
* the {@code CognitoEventService} to avoid optimistic lock exceptions.
* <p>
* The IDs are stored in the lock cache. The CognitoEventService looks up an ID
* in this cache before updating a workitem in a safe way.
* <p>
* It may happen that a user switches into edit mode
* ({@link WorkflowEvent#DOCUMENT_CHANGED}) without updating the workitem. For
* this reason a locked ID will be released after {@value #LOCK_TIMEOUT_SECONDS}
* seconds automatically.
* <p>
* <strong>Thread Safety:</strong> This implementation uses a
* {@link ConcurrentHashMap} to ensure thread-safe operations in a
* multi-user-environment where the same workitem can be opened by different
* users in parallel.
*
* @author rsoika
* @version 1.0
*/
@ApplicationScoped
public class CognitoLockHandler {
private static final Logger logger = Logger.getLogger(CognitoLockHandler.class.getName());
/**
* Lock timeout in seconds. After this duration, a lock is considered stale and
* will be automatically released.
*/
public static final long LOCK_TIMEOUT_SECONDS = 120;
/**
* Thread-safe cache storing workitem uniqueIds mapped to their lock timestamp.
* The timestamp is used to determine if a lock has expired.
*/
private final Map<String, Instant> lockCache = new ConcurrentHashMap<>();
/**
* WorkflowEvent listener that manages the lock cache based on document
* lifecycle events.
* <p>
* <ul>
* <li>{@link WorkflowEvent#DOCUMENT_CHANGED}: Adds the workitem's uniqueID to
* the lock cache (lock operation)</li>
* <li>{@link WorkflowEvent#DOCUMENT_AFTER_SAVE}: Removes the workitem's
* uniqueID from the lock cache (unlock operation)</li>
* </ul>
* <p>
* This observer is executed with {@link Interceptor.Priority#LIBRARY_BEFORE}
* priority to ensure it runs before other observers.
*
* @param workflowEvent the workflow event containing the workitem and event
* type
* @throws PluginException if an error occurs during event processing
*/
public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent)
throws PluginException {
int eventType = workflowEvent.getEventType();
String uniqueId = extractUniqueId(workflowEvent);
if (uniqueId == null || uniqueId.isEmpty()) {
logger.log(Level.FINE, "Skipping lock operation - workitem has no uniqueId");
return;
}
// Lock the workitem when user enters edit mode
if (WorkflowEvent.WORKITEM_CHANGED == eventType) {
lock(uniqueId);
logger.log(Level.INFO, "Workitem locked: uniqueId={0}, active locks={1}",
new Object[] { uniqueId, lockCache.size() });
}
// Unlock the workitem after successful save
if (WorkflowEvent.WORKITEM_AFTER_PROCESS == eventType) {
boolean wasLocked = unlock(uniqueId);
if (wasLocked) {
logger.log(Level.INFO, "Workitem unlocked after process: uniqueId={0}, remaining locks={1}",
new Object[] { uniqueId, lockCache.size() });
} else {
logger.log(Level.INFO, "Workitem was not locked (possibly expired): uniqueId={0}",
uniqueId);
}
}
}
/**
* Checks if the given workitem uniqueID is currently locked (in edit mode).
* <p>
* This method also performs cleanup of stale locks. If the lock for the given
* ID has exceeded the timeout ({@value #LOCK_TIMEOUT_SECONDS} seconds), it will
* be automatically removed and this method returns {@code false}.
*
* @param id the unique identifier of the workitem to check
* @return {@code true} if the workitem is currently locked and the lock has not
* expired, {@code false} otherwise
*/
public boolean isLocked(String id) {
if (id == null || id.isEmpty()) {
logger.log(Level.FINE, "isLocked called with null or empty id - returning false");
return false;
}
Instant lockTimestamp = lockCache.get(id);
if (lockTimestamp == null) {
logger.log(Level.FINE, "Workitem not locked: uniqueId={0}", id);
return false;
}
// Check if lock has expired
if (isLockExpired(lockTimestamp)) {
logger.log(Level.INFO, "Lock expired and removed: uniqueId={0}, locked since={1}",
new Object[] { id, lockTimestamp });
lockCache.remove(id);
return false;
}
long lockedSeconds = java.time.Duration.between(lockTimestamp, Instant.now()).getSeconds();
logger.log(Level.FINE, "Workitem is locked: uniqueId={0}, locked for {1}s",
new Object[] { id, lockedSeconds });
return true;
}
/**
* Adds a workitem uniqueID to the lock cache with the current timestamp.
* <p>
* If the ID is already in the cache, the timestamp will be updated (lock
* refresh).
*
* @param id the unique identifier of the workitem to lock
*/
public void lock(String id) {
if (id == null || id.isEmpty()) {
logger.log(Level.WARNING, "Attempted to lock with null or empty id - operation ignored");
return;
}
Instant previousLock = lockCache.put(id, Instant.now());
if (previousLock != null) {
logger.log(Level.FINE, "Lock refreshed: uniqueId={0}, previous lock from={1}",
new Object[] { id, previousLock });
} else {
logger.log(Level.FINE, "New lock created: uniqueId={0}", id);
}
// Opportunistic cleanup of expired locks
cleanupExpiredLocks();
}
/**
* Removes a workitem uniqueID from the lock cache.
*
* @param id the unique identifier of the workitem to unlock
* @return {@code true} if the workitem was locked and is now unlocked,
* {@code false} if the workitem was not locked
*/
public boolean unlock(String id) {
if (id == null || id.isEmpty()) {
logger.log(Level.WARNING, "Attempted to unlock with null or empty id - operation ignored");
return false;
}
Instant removed = lockCache.remove(id);
if (removed != null) {
long lockedDuration = java.time.Duration.between(removed, Instant.now()).getSeconds();
logger.log(Level.FINE, "Lock removed: uniqueId={0}, was locked for {1}s",
new Object[] { id, lockedDuration });
return true;
}
return false;
}
/**
* Returns the current number of active locks in the cache.
* <p>
* <strong>Note:</strong> This count may include expired locks that have not yet
* been cleaned up.
*
* @return the number of entries in the lock cache
*/
public int getLockCount() {
return lockCache.size();
}
/**
* Removes all expired locks from the cache.
* <p>
* This method is called opportunistically during lock operations to prevent
* unbounded cache growth.
*/
public void cleanupExpiredLocks() {
int initialSize = lockCache.size();
lockCache.entrySet().removeIf(entry -> {
boolean expired = isLockExpired(entry.getValue());
if (expired) {
logger.log(Level.FINE, "Cleaning up expired lock: uniqueId={0}, locked since={1}",
new Object[] { entry.getKey(), entry.getValue() });
}
return expired;
});
int removed = initialSize - lockCache.size();
if (removed > 0) {
logger.log(Level.INFO, "Expired locks cleanup completed: removed={0}, remaining={1}",
new Object[] { removed, lockCache.size() });
}
}
/**
* Checks if a lock timestamp has exceeded the timeout threshold.
*
* @param lockTimestamp the timestamp when the lock was created
* @return {@code true} if the lock is expired, {@code false} otherwise
*/
private boolean isLockExpired(Instant lockTimestamp) {
return lockTimestamp.plusSeconds(LOCK_TIMEOUT_SECONDS).isBefore(Instant.now());
}
/**
* Extracts the uniqueId from the workitem contained in the workflow event.
*
* @param workflowEvent the workflow event
* @return the uniqueId of the workitem, or {@code null} if not available
*/
private String extractUniqueId(WorkflowEvent workflowEvent) {
if (workflowEvent == null || workflowEvent.getWorkitem() == null) {
logger.log(Level.WARNING, "WorkflowEvent or workitem is null - cannot extract uniqueId");
return null;
}
String uniqueId = workflowEvent.getWorkitem().getUniqueID();
if (uniqueId == null || uniqueId.isEmpty()) {
logger.log(Level.FINE, "Workitem has no uniqueId (possibly a new document)");
}
return uniqueId;
}
}

View file

@ -1,139 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs.cognition;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.ai.workflow.ImixsAIPromptService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.EventLogService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.PluginException;
import ai.dynamixs.ChronicleTextBuilder;
import jakarta.inject.Inject;
/**
* The CognitoPlugin is a generic plugin to generate an cognito.create.event.
* This event is processed by the `CognitoEventService` to generate an AI based
* workflow abstract
* <p>
* The plugin can be activated by the following workflow result tag
*
* <pre>
{@code
<dynamixs-ai name="COGNITO" />
}
* </pre>
* <p>
* The embedded tag 'debug' is optional
*
* <p>
* The prompt definition is either loaded from the corresponding BPMN event
* (DataObject) or generated as generic default template in case that no
* PromptDefinition is assigned to the current event.
*
*
* @author rsoika
*
*/
public class CognitoPlugin extends org.imixs.ai.rag.workflow.RAGIndexPlugin {
private static final Logger logger = Logger.getLogger(CognitoPlugin.class.getName());
@Inject
private WorkflowService workflowService;
@Inject
private EventLogService eventLogService;
@Inject
private ImixsAIPromptService imixsAIPromptService;
@Override
public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException {
// do only run on type = workitem!
if (!workitem.getType().equals("workitem")) {
// no op!
return workitem;
}
// read optional configuration form the model or imixs.properties....
List<ItemCollection> cognitoAIDefinitions = workflowService.evalWorkflowResultXML(event, "dynamixs-ai",
"COGNITO", workitem, false);
// COGNITO Mode?
if (cognitoAIDefinitions != null && cognitoAIDefinitions.size() > 0) {
logger.info("├── running Dynamixs.AI Cognito Plugin");
// test if the event provides a Prompt template!
String promptTemplate = imixsAIPromptService.loadPromptTemplateByModelElement(event);
if (promptTemplate != null && !promptTemplate.isBlank()) {
logger.info("│ ├── loaded custom cognito prompt template from event");
} else {
promptTemplate = buildDefaultPromptTemplate(workitem);
logger.info("│ ├── created default cognito prompt template");
}
// we create a data object that holds the template
ItemCollection promptItemCol = new ItemCollection();
promptItemCol.setItemValue("category", "cognition");
promptItemCol.setItemValue(CognitoEventService.ITEM_PROMPT_DEFINITION, promptTemplate);
eventLogService.createEvent(CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT, workitem.getUniqueID(),
promptItemCol);
}
return workitem;
}
/**
* This method generates a generic prompt definition including a prompt template
* including the workflow chronicle data.
*
* @param workitem
* @return
*/
private String buildDefaultPromptTemplate(ItemCollection workitem) {
// generate default template
ChronicleTextBuilder chronicleTextBuilder = new ChronicleTextBuilder(workitem);
String promptTemplate = chronicleTextBuilder.build();
String result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<PromptDefinition>\n" + //
"\t<prompt_options>{\"n_predict\": 2048, \"temperature\": 0.2, \"top_p\": 0.9}</prompt_options>\n" + //
"\n" + //
" <prompt role=\"system\"><![CDATA[\n" + //
"You are a process analyst. A workflow has just been completed.\n" + //
"\n" + //
"Create a brief project insight:\n" + //
"- What specifically happened? (Include relevant names from people, companies, products when mentioned.)\n"
+ //
"- Is there anything unusual or important to remember for the future? (Pay attention to user comments - they often contain important warnings or decisions.)\n"
+ //
"\n" + //
"No general advice. Only project-specific facts and insights.]]>\n" + //
" </prompt>\n" + //
" <prompt role=\"user\"><![CDATA[\n" + promptTemplate + "]]>\n" + //
" </prompt>\n" + //
"\n" + //
"</PromptDefinition> ";
return result;
}
}

View file

@ -1,175 +0,0 @@
package ai.dynamixs;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.imixs.ai.ImixsAIContextHandler;
import org.imixs.ai.workflow.ImixsAIPromptService;
import org.imixs.ai.workflow.OpenAIAPIService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.ConditionalExpressionEvent;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.json.JsonObject;
import jakarta.transaction.TransactionScoped;
/**
* The ConditionalAIAdapter reacts on CDI Events of type BPMNConditionEvent and
* evaluates a condition against an LLM
* <p>
* The Adapter defines a Default Expression template for LLMs. The BPMN
* Configuration must only include the user prompt. See the following example:
* <p>
*
* <pre>
* {@code
<imixs-ai name="CONDITION">
<debug>true</debug>
<endpoint><propertyvalue>llm.service.endpoint</propertyvalue></endpoint>
<result-item>my.condition</result-item>
<prompt><![CDATA[
Is Germany an EU member country? ]]>
</prompt>
</imixs-ai>
* }
* </pre>
*
* Caching: The ConditionalAIAdapter implements a caching mechnaism. The adapter
* class stores the hash value in to the item <result-item>.hash to avoid
* duplicate calls against the llm with the same prompt in one processing cycle!
*/
@TransactionScoped
public class ConditionalAIAdapter implements Serializable {
private static final Logger logger = Logger.getLogger(ConditionalAIAdapter.class.getName());
// Transaction-scoped cache - survives across multiple eval() calls
private Map<Long, String> promptResultCache = new HashMap<>();
@Inject
protected WorkflowService workflowService;
@Inject
protected ImixsAIPromptService imixsAIPromptService;
@Inject
protected OpenAIAPIService llmService;
@Inject
ImixsAIContextHandler imixsAIContextHandler;
public static String DEFAULT_EXPRESSION_TEMPLATE = "<imixs-ai name=\"CONDITION\">\n" + //
" <debug>true</debug>\n" + //
" <endpoint><propertyvalue>llm.service.endpoint</propertyvalue></endpoint>\n" + //
" <result-event>BOOLEAN</result-event>\n" + //
" <PromptDefinition>\n" + //
" <prompt_options>{\"n_predict\": 16, \"temperature\": 0 }</prompt_options>\n" + //
" <prompt role=\"system\"><![CDATA[\n" + //
" Evaluate the following condition to 'true' or 'false'. Do only answer with 'true' or 'false'. Do not add any additional context into your answer.]]>\n"
+ //
" </prompt>\n" + //
" </PromptDefinition>\n" + //
"</imixs-ai>";
/**
* Test method
*
* @param conditionEvent
* @throws PluginException
* @throws AdapterException
*/
public void onConditionEvent(@Observes ConditionalExpressionEvent conditionalEvent)
throws PluginException, AdapterException {
// run only if we have a prompt definition
String condition = conditionalEvent.getCondition();
if (condition != null && condition.contains("<imixs-ai")) {
long l = System.currentTimeMillis();
List<ItemCollection> llmConditionDefinitions;
boolean llmAPIDebug = false;
condition = condition.trim();
llmConditionDefinitions = workflowService.evalXMLExpressionList(
conditionalEvent.getCondition(), "imixs-ai", "CONDITION", conditionalEvent.getWorkitem(), true);
for (ItemCollection promptDefinition : llmConditionDefinitions) {
String llmAPIEndpoint = imixsAIPromptService.parseLLMEndpointByBPMN(promptDefinition);
String userPrompt = promptDefinition.getItemValueString("prompt");
if ("true".equalsIgnoreCase(promptDefinition.getItemValueString("debug"))) {
llmAPIDebug = true;
}
if (llmAPIDebug) {
logger.info("├── evaluate conditional expression");
}
// set DEFAULT_EXPRESSION_TEMPLATE.
imixsAIContextHandler.setWorkItem(conditionalEvent.getWorkitem());
imixsAIContextHandler.addPromptDefinition(DEFAULT_EXPRESSION_TEMPLATE);
// add the user prompt!
imixsAIContextHandler.addMessage(ImixsAIContextHandler.ROLE_USER, userPrompt,
workflowService.getSessionContext().getCallerPrincipal().getName(), null);
// POST PromptCompletion
JsonObject jsonPrompt = imixsAIContextHandler.getOpenAIMessageObject();
if (llmAPIDebug) {
logger.info("│ ├── conditional prompt:");
logger.info(jsonPrompt.toString());
}
// Caching:
// if jsonPrompt (hash) was already stored, we do not call the LLM
long hashPrompt = jsonPrompt.hashCode();
// Check transaction-scoped cache
if (promptResultCache.containsKey(hashPrompt)) {
if (llmAPIDebug) {
logger.info("│ ├── reuse cached result from transaction cache - hash=" + hashPrompt);
logger.info("└── ✓ evaluation time: " + (System.currentTimeMillis() - l) + "ms");
}
conditionalEvent.setCondition(promptResultCache.get(hashPrompt));
return;
}
String completionResult = llmService.postPromptCompletion(imixsAIContextHandler, llmAPIEndpoint);
if (llmAPIDebug) {
logger.info("│ ├── ⚙ Completion Request conditional expression...");
}
String conditionalExpressionResult = llmService.processPromptResult(completionResult, "BOOLEAN",
conditionalEvent.getWorkitem());
// store the result message
if (conditionalExpressionResult != null && !conditionalExpressionResult.isBlank()) {
// trim result
conditionalExpressionResult = conditionalExpressionResult.trim().toLowerCase();
if (!"true".equals(conditionalExpressionResult) && !"false".equals(conditionalExpressionResult)) {
logger.warning(
"│ ├── ⚠ Unexpected conditional expression result: " + conditionalExpressionResult);
throw new PluginException(OpenAIAPIService.class.getSimpleName(),
OpenAIAPIService.ERROR_PROMPT_INFERENCE,
"Conditional expression should result into 'true' or 'false' only");
}
if (llmAPIDebug) {
logger.info("│ ├── ⚐ Conditional expression result: " + conditionalExpressionResult);
}
boolean booleanExpressionResult = Boolean.parseBoolean(conditionalExpressionResult.trim());
// Store in transaction-scoped cache
promptResultCache.put(hashPrompt, "" + booleanExpressionResult);
conditionalEvent.setCondition("" + booleanExpressionResult);
logger.info("└── ✓ evaluation time: " + (System.currentTimeMillis() - l) + "ms");
}
}
}
}
}

View file

@ -1,156 +0,0 @@
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>dynamixs-ai</artifactId>
<groupId>ai.dynamixs</groupId>
<version>1.0.2</version>
</parent>
<artifactId>dynamixs-ai-a2a</artifactId>
<packaging>jar</packaging>
<name>Dynamixs AI A2A Library</name>
<build>
<plugins>
<!-- use JDK settings for compiling -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.source}</source>
<target>${java.target}</target>
</configuration>
</plugin>
<!-- Testing JUnit 5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<!-- issue #572
hack for:
https://stackoverflow.com/questions/75116023/unable-to-make-protected-final-java-lang-class-java-lang-classloader-defineclass
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<argLine>
--add-opens java.base/java.lang=ALL-UNNAMED
</argLine>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Jakarta EE -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakarta.version}</version>
<scope>provided</scope>
</dependency>
<!-- Microprofile -->
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>${microprofile.version}</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<!-- Imixs Workflow -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-core</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-engine</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-jax-rs</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-faces</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>jakarta.json</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View file

@ -1,448 +0,0 @@
package ai.dynamixs.a2a;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
/**
* Represents an A2A Skill Card based on Imixs-Workflow BPMN models.
*
* The skill ID follows the pattern: {modelVersion}_{taskId}_{eventId} This
* allows direct mapping to Imixs workflow execution parameters.
*
* Example: "office-de-2.0_100_10" represents: - Model Version: "office-de-2.0"
* - Task ID: 100 - Event ID: 10
*/
public class A2ASkillCard implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(A2ASkillCard.class.getSimpleName());
// A2A Standard Fields
private String id; // {modelVersion}_{taskId}_{eventId}
private String name; // Human-readable skill name
private String description; // Detailed description
private List<String> tags; // Categorization tags
private List<String> examples; // Example usage scenarios
private List<String> inputModes; // Supported input media types
private List<String> outputModes; // Supported output media types
private Map<String, Object> metadata; // Additional metadata
// Constructors
public A2ASkillCard() {
this.tags = new ArrayList<>();
this.examples = new ArrayList<>();
this.inputModes = new ArrayList<>();
this.outputModes = new ArrayList<>();
this.metadata = new HashMap<>();
}
/**
* Id is computed by version, task and event id "invoice-workflow-2.1_100_10"
*
* @param modelVersion
* @param taskID
* @param eventID
*/
public A2ASkillCard(String modelVersion, int taskID, int eventID) {
this();
this.id = createSkillId(modelVersion, taskID, eventID);
}
// Imixs-specific convenience methods for parsing skill ID
/**
* Extracts the model version from the skill ID
*
* @return model version (e.g., "office-de-2.0")
*/
public String getModelVersion() {
if (id == null || !id.contains("_")) {
throw new IllegalStateException("Invalid skill ID format: " + id);
}
return id.substring(0, id.lastIndexOf('_', id.lastIndexOf('_') - 1));
}
/**
* Extracts the task ID from the skill ID
*
* @return Imixs task ID as integer
*/
public int getTaskId() {
if (id == null || !id.contains("_")) {
throw new IllegalStateException("Invalid skill ID format: " + id);
}
String[] parts = id.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid skill ID format: " + id);
}
try {
return Integer.parseInt(parts[parts.length - 2]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid task ID in skill ID: " + id, e);
}
}
/**
* Extracts the event ID from the skill ID
*
* @return Imixs event ID as integer
*/
public int getEventId() {
if (id == null || !id.contains("_")) {
throw new IllegalStateException("Invalid skill ID format: " + id);
}
String[] parts = id.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid skill ID format: " + id);
}
try {
return Integer.parseInt(parts[parts.length - 1]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid event ID in skill ID: " + id, e);
}
}
/**
* Creates a skill ID from Imixs workflow components
*
* @param modelVersion the workflow model version
* @param taskId the task ID
* @param eventId the event ID
* @return formatted skill ID
*/
public static String createSkillId(String modelVersion, int taskId, int eventId) {
if (modelVersion == null || modelVersion.trim().isEmpty()) {
throw new IllegalArgumentException("Model version cannot be null or empty");
}
return String.format("%s_%d_%d", modelVersion, taskId, eventId);
}
// JSON Serialization
/**
* Converts this skill card to a Jakarta JSON object
*
* @return JsonObject representation of this skill card
*/
public JsonObject toJsonObject() {
JsonObjectBuilder builder = Json.createObjectBuilder()
.add("id", id != null ? id : "")
.add("name", name != null ? name : "")
.add("description", description != null ? description : "");
// Tags array
JsonArrayBuilder tagsBuilder = Json.createArrayBuilder();
if (tags != null) {
tags.forEach(tagsBuilder::add);
}
builder.add("tags", tagsBuilder.build());
// Examples array
JsonArrayBuilder examplesBuilder = Json.createArrayBuilder();
if (examples != null) {
examples.forEach(examplesBuilder::add);
}
builder.add("examples", examplesBuilder.build());
// Input modes array
JsonArrayBuilder inputModesBuilder = Json.createArrayBuilder();
if (inputModes != null) {
inputModes.forEach(inputModesBuilder::add);
}
builder.add("inputModes", inputModesBuilder.build());
// Output modes array
JsonArrayBuilder outputModesBuilder = Json.createArrayBuilder();
if (outputModes != null) {
outputModes.forEach(outputModesBuilder::add);
}
builder.add("outputModes", outputModesBuilder.build());
// Metadata object
if (metadata != null && !metadata.isEmpty()) {
JsonObjectBuilder metadataBuilder = Json.createObjectBuilder();
metadata.forEach((key, value) -> {
if (value instanceof String) {
metadataBuilder.add(key, (String) value);
} else if (value instanceof Number) {
metadataBuilder.add(key, ((Number) value).doubleValue());
} else if (value instanceof Boolean) {
metadataBuilder.add(key, (Boolean) value);
} else if (value != null) {
metadataBuilder.add(key, value.toString());
}
});
builder.add("metadata", metadataBuilder.build());
}
return builder.build();
}
/**
* Creates an A2ASkillCard from a JSON string
*
* @param jsonString JSON representation of a skill card
* @return A2ASkillCard instance
*/
// public static A2ASkillCard fromJsonString(String jsonString) {
// try (JsonReader reader = Json.createReader(new
// java.io.StringReader(jsonString))) {
// JsonObject jsonObject = reader.readObject();
// return fromJsonObject(jsonObject);
// } catch (Exception e) {
// logger.severe("Failed to parse A2ASkillCard from JSON: " + e.getMessage());
// throw new IllegalArgumentException("Invalid JSON format for A2ASkillCard",
// e);
// }
// }
/**
* Creates an A2ASkillCard from a JsonObject
*
* @param jsonObject JsonObject representation
* @return A2ASkillCard instance
*/
public static A2ASkillCard fromJsonObject(JsonObject jsonObject) {
A2ASkillCard skill = new A2ASkillCard();
// Basic fields
skill.setId(jsonObject.getString("id", ""));
skill.setName(jsonObject.getString("name", ""));
skill.setDescription(jsonObject.getString("description", ""));
// Arrays
if (jsonObject.containsKey("tags")) {
JsonArray tagsArray = jsonObject.getJsonArray("tags");
skill.setTags(jsonArrayToStringList(tagsArray));
}
if (jsonObject.containsKey("examples")) {
JsonArray examplesArray = jsonObject.getJsonArray("examples");
skill.setExamples(jsonArrayToStringList(examplesArray));
}
if (jsonObject.containsKey("inputModes")) {
JsonArray inputModesArray = jsonObject.getJsonArray("inputModes");
skill.setInputModes(jsonArrayToStringList(inputModesArray));
}
if (jsonObject.containsKey("outputModes")) {
JsonArray outputModesArray = jsonObject.getJsonArray("outputModes");
skill.setOutputModes(jsonArrayToStringList(outputModesArray));
}
// Metadata
if (jsonObject.containsKey("metadata")) {
JsonObject metadataObject = jsonObject.getJsonObject("metadata");
Map<String, Object> metadata = new HashMap<>();
metadataObject.forEach((key, value) -> {
switch (value.getValueType()) {
case STRING:
metadata.put(key, ((JsonString) value).getString());
break;
case NUMBER:
metadata.put(key, ((jakarta.json.JsonNumber) value).doubleValue());
break;
case TRUE:
metadata.put(key, Boolean.TRUE);
break;
case FALSE:
metadata.put(key, Boolean.FALSE);
break;
default:
metadata.put(key, value.toString());
}
});
skill.setMetadata(metadata);
}
return skill;
}
/**
* Helper method to convert JsonArray to List<String>
*/
private static List<String> jsonArrayToStringList(JsonArray jsonArray) {
List<String> list = new ArrayList<>();
for (JsonValue value : jsonArray) {
if (value.getValueType() == JsonValue.ValueType.STRING) {
list.add(((JsonString) value).getString());
} else {
list.add(value.toString());
}
}
return list;
}
// Validation
/**
* Validates this skill card for A2A compliance
*
* @return true if valid, false otherwise
*/
public boolean isValid() {
if (id == null || id.trim().isEmpty()) {
logger.warning("Skill card validation failed: missing ID");
return false;
}
if (name == null || name.trim().isEmpty()) {
logger.warning("Skill card validation failed: missing name");
return false;
}
if (description == null || description.trim().isEmpty()) {
logger.warning("Skill card validation failed: missing description");
return false;
}
// Validate skill ID format
try {
getModelVersion();
getTaskId();
getEventId();
} catch (Exception e) {
logger.warning("Skill card validation failed: invalid ID format: " + id);
return false;
}
return true;
}
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags != null ? tags : new ArrayList<>();
}
public List<String> getExamples() {
return examples;
}
public void setExamples(List<String> examples) {
this.examples = examples != null ? examples : new ArrayList<>();
}
public List<String> getInputModes() {
return inputModes;
}
public void setInputModes(List<String> inputModes) {
this.inputModes = inputModes != null ? inputModes : new ArrayList<>();
}
public List<String> getOutputModes() {
return outputModes;
}
public void setOutputModes(List<String> outputModes) {
this.outputModes = outputModes != null ? outputModes : new ArrayList<>();
}
public Map<String, Object> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata != null ? metadata : new HashMap<>();
}
// Convenience methods for metadata
/**
* Adds a metadata entry
*/
public void addMetadata(String key, Object value) {
if (metadata == null) {
metadata = new HashMap<>();
}
metadata.put(key, value);
}
/**
* Gets a metadata value as String
*/
public String getMetadataString(String key) {
Object value = metadata != null ? metadata.get(key) : null;
return value != null ? value.toString() : null;
}
/**
* Gets a metadata value as Boolean
*/
public Boolean getMetadataBoolean(String key) {
Object value = metadata != null ? metadata.get(key) : null;
if (value instanceof Boolean) {
return (Boolean) value;
}
return null;
}
// toString for debugging
@Override
public String toString() {
return String.format("A2ASkillCard{id='%s', name='%s', modelVersion='%s', taskId=%d, eventId=%d}",
id, name,
id != null ? getModelVersion() : "unknown",
id != null ? getTaskId() : -1,
id != null ? getEventId() : -1);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
A2ASkillCard that = (A2ASkillCard) obj;
return id != null ? id.equals(that.id) : that.id == null;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}

View file

@ -1,436 +0,0 @@
/*******************************************************************************
* Imixs Workflow
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Project:
* http://www.imixs.org
* http://java.net/projects/imixs-workflow
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika - Software Developer
*******************************************************************************/
package ai.dynamixs.a2a;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
/**
* The TextblockRestService provides methods to access the content of a textbock
* in various ways.
*
* @author rsoika
*
*/
@Named
@RequestScoped
@Path("/a2a/")
@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.TEXT_PLAIN })
public class A2ASkillCardRestService implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(A2ASkillCardRestService.class.getSimpleName());
@Context
UriInfo uriInfo;
@Inject
A2ASkillService a2aSkillService;
/**
* A2A Agent Card Discovery Endpoint According to RFC 8615 - Well-Known URIs
* URL: /.well-known/agent.json
*/
@GET
@Path("/.well-known/agent.json")
@Produces({ MediaType.APPLICATION_JSON })
public Response getAgentCard() {
try {
JsonObject agentCard = buildAgentCard();
return Response.ok(agentCard).build();
} catch (Exception e) {
logger.severe("Error creating agent card: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", null))
.build();
}
}
/**
* A2A JSON-RPC 2.0 Endpoint All A2A protocol methods are handled here URL:
* /a2a/v1 (as specified in Agent Card)
*/
@POST
@Path("/a2a/v1")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response handleJsonRpcRequest(JsonObject request) {
try {
// Validate JSON-RPC 2.0 structure
if (!isValidJsonRpcRequest(request)) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(buildJsonRpcError(-32600, "Invalid Request", null))
.build();
}
String method = request.getString("method");
Object id = request.get("id");
JsonObject params = request.getJsonObject("params");
// Route to appropriate A2A method
switch (method) {
case "message/send":
return handleMessageSend(id, params);
case "tasks/get":
return handleTasksGet(id, params);
case "tasks/cancel":
return handleTasksCancel(id, params);
case "agent/authenticatedExtendedCard":
return handleAuthenticatedExtendedCard(id, params);
default:
return Response.status(Response.Status.NOT_FOUND)
.entity(buildJsonRpcError(-32601, "Method not found", id))
.build();
}
} catch (Exception e) {
logger.severe("Error processing JSON-RPC request: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", null))
.build();
}
}
/**
* Builds the A2A compliant Agent Card
*/
private JsonObject buildAgentCard() {
// Security schemes for authentication
JsonObject securitySchemes = Json.createObjectBuilder()
.add("bearer", Json.createObjectBuilder()
.add("type", "http")
.add("scheme", "bearer")
.add("bearerFormat", "JWT")
.build())
.add("apiKey", Json.createObjectBuilder()
.add("type", "apiKey")
.add("in", "header")
.add("name", "X-API-Key")
.build())
.build();
// Security requirements
JsonArray security = Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("bearer", Json.createArrayBuilder().build())
.build())
.build();
// Agent capabilities
JsonObject capabilities = Json.createObjectBuilder()
.add("streaming", false) // SSE not implemented yet
.add("pushNotifications", false) // Push notifications not implemented yet
.add("stateTransitionHistory", false)
.build();
// Agent provider information
JsonObject provider = Json.createObjectBuilder()
.add("organization", "Dynamixs.AI")
.add("url", "https://www.dynamixs.ai")
.build();
// Skills array
JsonArray skills = buildA2ASkills();
// Build complete A2A Agent Card
JsonObjectBuilder cardBuilder = Json.createObjectBuilder()
.add("name", "Dynamixs.AI Processing Agent")
.add("description",
"An agent for processing business documents and tasks.")
.add("url", getBaseUrl() + "a2a/v1") // JSON-RPC endpoint
.add("provider", provider)
.add("version", "1.0.0")
.add("documentationUrl", getBaseUrl() + "docs/a2a")
.add("capabilities", capabilities)
.add("securitySchemes", securitySchemes)
.add("security", security)
.add("defaultInputModes", Json.createArrayBuilder()
.add("text/plain")
.add("application/json")
.build())
.add("defaultOutputModes", Json.createArrayBuilder()
.add("text/plain")
.add("application/json")
.add("text/html")
.build())
.add("skills", skills)
.add("supportsAuthenticatedExtendedCard", false); // Simplified for now
return cardBuilder.build();
}
/**
* Builds A2A compliant skills array
*/
private JsonArray buildA2ASkills() {
logger.info("Starting to build A2A skills...");
List<A2ASkillCard> skills = a2aSkillService.parseModels();
logger.info("parseModels() returned " + (skills != null ? skills.size() : "null") + " skills");
if (skills != null) {
for (A2ASkillCard skill : skills) {
logger.info("Skill found: " + skill.getId() + " - Valid: " + skill.isValid());
if (!skill.isValid()) {
logger.warning("Invalid skill: " + skill);
}
}
}
List<A2ASkillCard> validSkills = skills.stream()
.filter(A2ASkillCard::isValid)
.collect(Collectors.toList());
logger.info("Valid skills after filtering: " + validSkills.size());
return validSkills.stream()
.map(A2ASkillCard::toJsonObject)
.collect(Json::createArrayBuilder,
JsonArrayBuilder::add,
JsonArrayBuilder::addAll)
.build();
}
/**
* Handle A2A message/send method
*/
private Response handleMessageSend(Object id, JsonObject params) {
try {
// Extract message from params
JsonObject message = params.getJsonObject("message");
if (message == null) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(buildJsonRpcError(-32602, "Invalid params: missing message",
id))
.build();
}
// Process the message and create a task
String taskId = generateTaskId();
String contextId = generateContextId();
// For demo: create a simple completed task
JsonObject task = Json.createObjectBuilder()
.add("id", taskId)
.add("contextId", contextId)
.add("status", Json.createObjectBuilder()
.add("state", "completed")
.add("timestamp", getCurrentTimestamp())
.build())
.add("artifacts", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("artifactId", generateArtifactId())
.add("name", "Processing Result")
.add("parts", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("kind", "text")
.add("text", "Task completed successfully. Message processed: "
+
message.getJsonArray(
"parts")
.getJsonObject(0)
.getString("text",
""))
.build())
.build())
.build())
.build())
.add("history", Json.createArrayBuilder()
.add(message)
.build())
.add("kind", "task")
.build();
// Return JSON-RPC success response
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", task)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in message/send: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", id))
.build();
}
}
/**
* Handle A2A tasks/get method
*/
private Response handleTasksGet(Object id, JsonObject params) {
try {
String taskId = params.getString("id");
// For demo: return a mock task
JsonObject task = Json.createObjectBuilder()
.add("id", taskId)
.add("contextId", generateContextId())
.add("status", Json.createObjectBuilder()
.add("state", "completed")
.add("timestamp", getCurrentTimestamp())
.build())
.add("kind", "task")
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", task)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in tasks/get: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32001, "Task not found", id))
.build();
}
}
/**
* Handle A2A tasks/cancel method
*/
private Response handleTasksCancel(Object id, JsonObject params) {
try {
String taskId = params.getString("id");
JsonObject task = Json.createObjectBuilder()
.add("id", taskId)
.add("contextId", generateContextId())
.add("status", Json.createObjectBuilder()
.add("state", "canceled")
.add("timestamp", getCurrentTimestamp())
.build())
.add("kind", "task")
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", task)
.build();
return Response.ok(response).build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32002, "Task cannot be canceled", id))
.build();
}
}
/**
* Handle authenticated extended card (not implemented)
*/
private Response handleAuthenticatedExtendedCard(Object id, JsonObject params) {
return Response.status(Response.Status.NOT_IMPLEMENTED)
.entity(buildJsonRpcError(-32004, "This operation is not supported", id))
.build();
}
/**
* Validates JSON-RPC 2.0 request structure
*/
private boolean isValidJsonRpcRequest(JsonObject request) {
return request.containsKey("jsonrpc") &&
"2.0".equals(request.getString("jsonrpc")) &&
request.containsKey("method") &&
request.containsKey("id");
}
/**
* Builds a JSON-RPC 2.0 error response
*/
private JsonObject buildJsonRpcError(int code, String message, Object id) {
JsonObjectBuilder errorBuilder = Json.createObjectBuilder()
.add("code", code)
.add("message", message);
JsonObjectBuilder responseBuilder = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("error", errorBuilder.build());
if (id != null) {
responseBuilder.add("id", id.toString());
} else {
responseBuilder.addNull("id");
}
return responseBuilder.build();
}
/**
* Helper methods for generating IDs and timestamps
*/
private String generateTaskId() {
return java.util.UUID.randomUUID().toString();
}
private String generateContextId() {
return java.util.UUID.randomUUID().toString();
}
private String generateArtifactId() {
return java.util.UUID.randomUUID().toString();
}
private String getCurrentTimestamp() {
return java.time.Instant.now().toString();
}
private String getBaseUrl() {
return uriInfo.getBaseUri().toString();
}
}

View file

@ -1,152 +0,0 @@
/*******************************************************************************
* Imixs Workflow
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Project:
* http://www.imixs.org
* http://java.net/projects/imixs-workflow
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika - Software Developer
*******************************************************************************/
package ai.dynamixs.a2a;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.ModelManager;
import org.imixs.workflow.engine.ModelService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.openbpmn.bpmn.BPMNModel;
import jakarta.annotation.security.DeclareRoles;
import jakarta.annotation.security.RolesAllowed;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
/**
* The A2ASkillService parses the model information to provide A2ASkillCards
*
* @author rsoika
*/
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS",
"org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
"org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS",
"org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
"org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@Stateless
@LocalBean
public class A2ASkillService {
@Inject
ModelService modelService;
@Inject
WorkflowService workflowService;
private static Logger logger = Logger.getLogger(A2ASkillService.class
.getName());
/**
* This method iterates over all models and returns a list of skill card objects
*
* The method tests if a event has a <imixs-ai name="SKILL"> tag.
*
*/
public List<A2ASkillCard> parseModels() {
logger.log(Level.INFO, "├── 🔃 parsing A2A SkillCards....");
List<A2ASkillCard> result = new ArrayList<>();
ModelManager modelManager = new ModelManager(workflowService);
List<String> versions = modelService.getVersions();
try {
for (String version : versions) {
logger.log(Level.INFO, "│ ├── {0}", version);
BPMNModel model = modelManager.getModel(version);
Set<String> groups = modelManager.findAllGroupsByModel(model);
for (String group : groups) {
List<ItemCollection> tasks = modelManager.findTasks(model, group);
for (ItemCollection task : tasks) {
int taskID = task.getItemValueInteger("taskid");
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
for (ItemCollection event : events) {
int eventID = event.getItemValueInteger("eventid");
// test if we have a <imixs-ai name="SKILL">
try {
List<ItemCollection> llmPromptDefinitions = workflowService.evalWorkflowResultXML(event,
"imixs-ai",
"SKILL", null, false);
// did we found a skill?
for (ItemCollection skillItemCol : llmPromptDefinitions) {
A2ASkillCard skillCard = new A2ASkillCard(version, taskID, eventID);
skillCard.setName(event.getItemValueString("name"));
skillCard.setDescription(skillItemCol.getItemValueString("description"));
String tags = skillItemCol.getItemValueString("tags");
if (tags != null && !tags.isBlank()) {
String[] parts = tags.split(",\\s*");
skillCard.setTags(Arrays.asList(parts));
}
skillCard.setExamples(skillItemCol.getItemValueList("example", String.class));
// skillCard.addMetadata("aea", versions);
if (skillCard.isValid()) {
result.add(skillCard);
}
}
} catch (PluginException e) {
// no match
}
}
}
}
}
} catch (ModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
}

View file

@ -1,30 +0,0 @@
Imixs-Office-Workflow
Copyright (C) 2001-2018 Imixs Software Solutions GmbH,
http://www.imixs.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Project:
http://www.imixs.org
Contributors:
Imixs Software Solutions GmbH - initial API and implementation
Ralph Soika - Software Developer

View file

@ -1,621 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
bean-discovery-mode="all" version="3.0">
</beans>

View file

@ -1,10 +0,0 @@
Imixs Workflow Technology
Copyright (C) 2010 Imixs Software Solutions GmbH,
http://www.imixs.com
Contributors:
Imixs Software Solutions GmbH - initial implementation
Ralph Soika

View file

@ -1,392 +0,0 @@
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>dynamixs-ai</artifactId>
<groupId>ai.dynamixs</groupId>
<version>1.0.1</version>
</parent>
<artifactId>dynamixs-ai-app</artifactId>
<packaging>war</packaging>
<name>Dynamixs AI Web App</name>
<profiles>
<profile>
<id>debug</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<exec executable="docker">
<arg value="build" />
<arg value="-f" />
<arg value="../Dockerfile-debug" />
<arg value="-t" />
<arg value="imixs/${imixs-office.applicationname}" />
<arg value="./." />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>imixs-cloud</id>
<!-- Imixs Security OIDC -->
<dependencies>
<dependency>
<groupId>org.imixs.security</groupId>
<artifactId>imixs-oidc</artifactId>
<version>${org.imixs.security.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.imixs.security</groupId>
<artifactId>imixs-oidc-marty</artifactId>
<version>${org.imixs.security.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<exec executable="docker">
<arg value="build" />
<arg value="-t" />
<arg
value="imixs/${imixs-office.applicationname}:${project.version}" />
<arg value="../." />
</exec>
<exec executable="docker">
<arg value="tag" />
<arg
value="imixs/${imixs-office.applicationname}:${project.version}" />
<arg
value="${org.imixs.docker.registry}/imixs/${imixs-office.applicationname}:${project.version}" />
</exec>
<exec executable="docker">
<arg value="push" />
<arg
value="${org.imixs.docker.registry}/imixs/${imixs-office.applicationname}:${project.version}" />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<resources>
<!-- enable resource filtering for multi language version -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<filtering>true</filtering>
<!-- this is relative to the pom.xml directory -->
<directory>${custom.webResources}</directory>
<includes>
<include>**/WEB-INF/*</include>
<!-- include any other file types you want to filter -->
</includes>
</resource>
</webResources>
<workDirectory>target/overlay-war-folder</workDirectory>
<!-- We exclude libs form the parent WAR artifact -->
<overlays>
<overlay>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-office-workflow-app</artifactId>
<excludes>
<exclude>WEB-INF/lib/*.jar</exclude>
</excludes>
</overlay>
</overlays>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.imixs.maven</groupId>
<artifactId>manik-hotdeploy-maven-plugin</artifactId>
<version>2.0.0</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- List Source and Target folders for Autodeploy and Hotdeploy -->
<autodeployments>
<deployment>
<!-- wildcard deployment -->
<source>target/*.{war,ear,jar}</source>
<target>../docker/deployments/</target>
<unpack>true</unpack>
</deployment>
</autodeployments>
<hotdeployments>
<deployment>
<source>src/main/webapp</source>
<target>../docker/deployments/dynamixs-ai.war</target>
</deployment>
</hotdeployments>
</configuration>
</plugin>
</plugins>
<finalName>dynamixs-ai</finalName>
</build>
<dependencies>
<!-- Imixs Workflow -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-core</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-engine</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-jax-rs</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-faces</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-index-lucene</artifactId>
<version>${org.imixs.workflow.version}</version>
</dependency>
<!-- A2A -->
<dependency>
<groupId>ai.dynamixs</groupId>
<artifactId>dynamixs-ai-a2a</artifactId>
<type>jar</type>
<version>${project.version}</version>
</dependency>
<!-- MCP -->
<dependency>
<groupId>ai.dynamixs</groupId>
<artifactId>dynamixs-ai-mcp</artifactId>
<type>jar</type>
<version>${project.version}</version>
</dependency>
<!-- Marty -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-marty</artifactId>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-metrics-monitor</artifactId>
</dependency>
<!-- Imixs-Office-Workflow Overlay -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-office-workflow-app</artifactId>
<type>war</type>
<version>${org.imixs.office.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-office-workflow-util</artifactId>
<version>${org.imixs.office.version}</version>
</dependency>
<!-- Imixs-Archive -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-archive-api</artifactId>
<version>${org.imixs.archive.version}</version>
</dependency>
<!-- Imixs Data -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-data-groups</artifactId>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-data-views</artifactId>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-data-documents</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-data-importer</artifactId>
<scope>compile</scope>
</dependency>
<!-- -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${apache.pdfbox.version}</version>
</dependency>
<!-- Imixs-AI -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-ai-rag</artifactId>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-ai-workflow</artifactId>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-ai-bpmn</artifactId>
</dependency>
<!-- Imixs-QR-Code -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-qrcode</artifactId>
</dependency>
<!-- Imixs-Wopi -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-wopi</artifactId>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-odf</artifactId>
</dependency>
<!-- Imixs Signature Feature -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-signature-api</artifactId>
<version>${org.imixs.signature.version}</version>
</dependency>
<!-- SEPA -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-sepa</artifactId>
</dependency>
<!-- DATEV -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-datev</artifactId>
</dependency>
<!-- POI Adapter -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-adapters-poi</artifactId>
</dependency>
<!-- OIDC
<dependency>
<groupId>org.imixs.security</groupId>
<artifactId>imixs-oidc</artifactId>
<version>3.0.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.imixs.security</groupId>
<artifactId>imixs-oidc-marty</artifactId>
<version>3.0.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
-->
</dependencies>
</project>

View file

@ -1,546 +0,0 @@
package ai.dynamixs;
/*******************************************************************************
* Imixs Workflow Technology
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika
*
*******************************************************************************/
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.imixs.ai.workflow.ImixsAIPromptEvent;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.ItemCollectionComparator;
import org.imixs.workflow.WorkflowKernel;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.plugins.HistoryPlugin;
import org.imixs.workflow.exceptions.QueryException;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
/**
* The ChronicleTextBuilder is a CDI Bean observing the CDI event
* `ImixsAIPromptEvent` and replaces the placeholder {chronicle} with the
* chronicle data of the given workitem.
* <p>
* The class creates a text representation of all chronicle data for a given
* workitem.
* <p>
* The output format is structured by year and month:
*
* <pre>
* 2025
*
* December
* 27. Dec 2025 (14:37) - Ralph Soika
* Offer sent
* Products are out of stock now!
*
* 27. Dec 2025 (14:35) - imixs-workflow-service
* Retrieve Products
* Retrieve Address
* </pre>
*
* <p>
* Usage example:
*
* <pre>
* ChronicleTextBuilder builder = new ChronicleTextBuilder(workitem, locale);
* builder.setDmsController(dmsController);
* builder.setWorkitemLinkController(workitemLinkController);
* builder.setWorkitemService(workitemService);
* builder.setDocumentService(documentService);
* String chronicleText = builder.build();
* </pre>
*
* <p>
* The builder supports filtering by entry type (history, comment, dms,
* reference, version, imixs-ai).
*
* @author rsoika
*/
public class ChronicleTextBuilder implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ChronicleTextBuilder.class.getName());
private ItemCollection workitem;
private Locale locale;
private String filterType;
// @Inject
// private WorkitemService workitemService;
@Inject
private DocumentService documentService;
// Internal data structures
private List<ChronicleEntry> chronicleEntries;
private Map<Integer, Set<Integer>> yearsMonths;
// Date formatters
private DateTimeFormatter dayFormatter;
private DateTimeFormatter timeFormatter;
private DateTimeFormatter monthFormatter;
/**
* Default constructor
*/
public ChronicleTextBuilder() {
this.locale = Locale.ENGLISH;
this.filterType = null;
this.chronicleEntries = new ArrayList<>();
this.yearsMonths = new HashMap<>();
// Initialize date formatters
this.dayFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy", this.locale);
this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm", this.locale);
this.monthFormatter = DateTimeFormatter.ofPattern("MMMM", this.locale);
}
/**
* Constructor with workitem and locale.
*
* @param workitem the workitem to build the chronicle for
* @param locale the locale for date formatting (e.g., Locale.ENGLISH,
* Locale.GERMAN)
*/
public ChronicleTextBuilder(ItemCollection workitem, Locale locale) {
this.workitem = workitem;
this.locale = locale != null ? locale : Locale.ENGLISH;
this.filterType = null;
this.chronicleEntries = new ArrayList<>();
this.yearsMonths = new HashMap<>();
// Initialize date formatters
this.dayFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy", this.locale);
this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm", this.locale);
this.monthFormatter = DateTimeFormatter.ofPattern("MMMM", this.locale);
}
/**
* Constructor with workitem only (uses English locale as default).
*
* @param workitem the workitem to build the chronicle for
*/
public ChronicleTextBuilder(ItemCollection workitem) {
this(workitem, Locale.ENGLISH);
}
/**
* This CDI class reacts on the CDI Event `ImixsAIPromptEvent` and replaces the
* placeholder {chronicle} with the chronicle data of the given workitem.
*
* @param event
*/
public void onEvent(@Observes ImixsAIPromptEvent event) {
if (event.getWorkitem() == null) {
return;
}
String prompt = event.getPromptTemplate();
if (prompt.contains("{chronicle}")) {
this.workitem = event.getWorkitem();
String result = build();
prompt = prompt.replace("{chronicle}", result);
// update the prompt tempalte
event.setPromptTemplate(prompt);
}
}
/**
* Sets a filter to include only entries of a specific type. Valid types:
* history, comment, dms, reference, version, imixs-ai
*
* @param filterType the type to filter by, or null to include all
* @return this builder for method chaining
*/
public ChronicleTextBuilder setFilter(String filterType) {
this.filterType = filterType;
return this;
}
/**
* Builds and returns the text representation of the chronicle.
*
* @return formatted chronicle text
*/
public String build() {
long startTime = System.currentTimeMillis();
if (workitem == null) {
return "";
}
// Collect all chronicle data
collectHistoryEntries();
collectCommentEntries();
collectDMSEntries();
collectVersionEntries();
// Sort entries by date (newest first)
Collections.sort(chronicleEntries, new ChronicleEntryComparator(false));
// Build the text output
String result = buildTextOutput();
logger.fine("ChronicleTextBuilder.build() completed in " + (System.currentTimeMillis() - startTime) + "ms");
return result;
}
/**
* Collects workflow history entries from the workitem.
*/
@SuppressWarnings("unchecked")
private void collectHistoryEntries() {
List<List<?>> history = null;
// Check for deprecated field 'txtworkflowhistory'
if (!workitem.hasItem(HistoryPlugin.ITEM_HISTORY_LOG)
&& workitem.hasItem("txtworkflowhistory")) {
history = workitem.getItemValue("txtworkflowhistory");
// Sort old history entries chronologically
Collections.sort(history, new Comparator<List<?>>() {
@Override
public int compare(List<?> entry1, List<?> entry2) {
Date date1 = (Date) entry1.get(0);
Date date2 = (Date) entry2.get(0);
return date1.compareTo(date2);
}
});
} else {
history = workitem.getItemValue(HistoryPlugin.ITEM_HISTORY_LOG);
}
// Reverse to get newest first
// Collections.reverse(history);
if (history.size() > 0 && history.get(0) instanceof List) {
for (List<?> entries : history) {
Date date = (Date) entries.get(0);
String message = (String) entries.get(1);
String user = (String) entries.get(2);
addEntry(date, user, message, "history");
}
}
}
/**
* Collects comment entries from the workitem.
*/
private void collectCommentEntries() {
List<Map<String, List<Object>>> comments = workitem.getItemValue("txtCommentLog");
for (Map<String, List<Object>> comment : comments) {
ItemCollection itemCol = new ItemCollection(comment);
Date date = itemCol.getItemValueDate("datcomment");
String message = itemCol.getItemValueString("txtcomment");
String user = itemCol.getItemValueString("nameditor");
addEntry(date, user, message, "comment");
}
}
/**
* Collects DMS (attachment) entries if dmsController is available.
*/
private void collectDMSEntries() {
List<FileData> fileDataList = workitem.getFileData();
for (FileData fileData : fileDataList) {
ItemCollection fileAttributes = new ItemCollection(fileData.getAttributes());
String content = fileAttributes.getItemValueString("text");
if (!content.isBlank()) {
String user = fileAttributes.getItemValueString("$creator");
Date date = fileAttributes.getItemValueDate("$created");
if (fileData.getAttribute("$modified") != null) {
date = fileAttributes.getItemValueDate("$modified");
}
if (date == null) {
date = new Date();
}
addEntry(date, user, "Attachment: " + fileData.getName() + "\n\n" + content + "\n\n", "dms");
}
}
}
/**
* Collects version entries if workitemService and documentService are
* available.
*/
private void collectVersionEntries() {
List<ItemCollection> versions = findAllVersions(workitem);
for (ItemCollection version : versions) {
// Skip current workitem
if (workitem.getUniqueID().equals(version.getUniqueID())) {
continue;
}
ItemCollection versionFull = documentService.load(version.getUniqueID());
Date date = version.getItemValueDate(WorkflowKernel.CREATED);
String message = version.getItemValueString("$WorkflowSummary");
String user = version.getItemValueString(WorkflowKernel.EDITOR);
if (!versionFull.getItemValueString("$uniqueIdSource").isEmpty()) {
if (versionFull.hasItem(WorkflowKernel.CREATED + ".version")) {
date = versionFull.getItemValueDate(WorkflowKernel.CREATED + ".version");
}
message = "Version (Branch): " + message;
} else {
message = "Version: " + message;
}
addEntry(date, user, message, "version");
}
}
/**
* Adds a chronicle entry to the internal list. Applies filter if set and
* updates the year/month index.
*/
private void addEntry(Date date, String user, String message, String type) {
if (date == null) {
return;
}
// Apply filter if set
if (filterType != null && !filterType.isEmpty() && !filterType.equals(type)) {
return;
}
// Truncate to minutes
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
localDateTime = localDateTime.truncatedTo(ChronoUnit.MINUTES);
ChronicleEntry entry = new ChronicleEntry(localDateTime, user, message, type);
chronicleEntries.add(entry);
// Update year/month index
LocalDate localDate = localDateTime.toLocalDate();
int year = localDate.getYear();
int month = localDate.getMonthValue();
yearsMonths.computeIfAbsent(year, k -> new HashSet<>()).add(month);
}
/**
* Builds the formatted text output from collected entries.
*/
private String buildTextOutput() {
StringBuilder sb = new StringBuilder();
// Add title
sb.append(
"# " + workitem.getWorkflowGroup() + " : " + workitem.getItemValueString(WorkflowKernel.WORKFLOWSTATUS))
.append("\n\n");
// Get sorted years (descending)
List<Integer> years = new ArrayList<>(yearsMonths.keySet());
for (int i = 0; i < years.size(); i++) {
int year = years.get(i);
// Year header
// sb.append(year).append("\n\n");
// Get sorted months for this year (descending)
List<Integer> months = new ArrayList<>(yearsMonths.get(year));
for (int j = 0; j < months.size(); j++) {
int month = months.get(j);
// Get entries for this month
List<ChronicleEntry> monthEntries = getEntriesForMonth(year, month);
if (monthEntries.isEmpty()) {
continue;
}
// Month header
// String monthName = LocalDate.of(year, month, 1).format(monthFormatter);
// sb.append(monthName).append("\n\n");
// Group entries by user and timestamp
List<GroupedEntry> groupedEntries = groupEntries(monthEntries);
for (GroupedEntry grouped : groupedEntries) {
// Format: "27. Dec 2025 (14:37) - Ralph Soika"
String dayStr = grouped.dateTime.format(dayFormatter);
String timeStr = grouped.dateTime.format(timeFormatter);
sb.append("\n" + dayStr).append(" (").append(timeStr).append(") - ").append(grouped.user)
.append("\n");
// Add all messages for this group
for (String message : grouped.messages) {
sb.append(message).append("\n");
}
}
// Add spacing between months (but not after the last month of the last year)
if (j < months.size() - 1 || i < years.size() - 1) {
sb.append("\n");
}
}
}
return sb.toString().trim();
}
/**
* Returns all entries for a specific year and month.
*/
private List<ChronicleEntry> getEntriesForMonth(int year, int month) {
List<ChronicleEntry> result = new ArrayList<>();
for (ChronicleEntry entry : chronicleEntries) {
if (entry.dateTime.getYear() == year && entry.dateTime.getMonthValue() == month) {
result.add(entry);
}
}
return result;
}
/**
* Groups entries by user and timestamp (same minute). This consolidates
* multiple actions by the same user at the same time.
*/
private List<GroupedEntry> groupEntries(List<ChronicleEntry> entries) {
List<GroupedEntry> grouped = new ArrayList<>();
GroupedEntry current = null;
for (ChronicleEntry entry : entries) {
if (current == null ||
!current.user.equals(entry.user) ||
!current.dateTime.equals(entry.dateTime)) {
// Start a new group
current = new GroupedEntry(entry.dateTime, entry.user);
grouped.add(current);
}
current.messages.add(entry.message);
}
return grouped;
}
/**
* Internal class representing a single chronicle entry.
*/
private static class ChronicleEntry {
LocalDateTime dateTime;
String user;
String message;
String type;
ChronicleEntry(LocalDateTime dateTime, String user, String message, String type) {
this.dateTime = dateTime;
this.user = user != null ? user : "";
this.message = message != null ? message : "";
this.type = type;
}
}
/**
* Internal class for grouping entries by user and timestamp.
*/
private static class GroupedEntry {
LocalDateTime dateTime;
String user;
List<String> messages;
GroupedEntry(LocalDateTime dateTime, String user) {
this.dateTime = dateTime;
this.user = user;
this.messages = new ArrayList<>();
}
}
/**
* Comparator for sorting chronicle entries by date.
*/
private static class ChronicleEntryComparator implements Comparator<ChronicleEntry> {
private boolean descending;
ChronicleEntryComparator(boolean descending) {
this.descending = descending;
}
@Override
public int compare(ChronicleEntry e1, ChronicleEntry e2) {
int result = e1.dateTime.compareTo(e2.dateTime);
return descending ? -result : result;
}
}
/**
* This method finds all versions of a given workitem.
*
*/
private List<ItemCollection> findAllVersions(ItemCollection workitem) {
List<ItemCollection> versions = new ArrayList<ItemCollection>();
if (null == workitem)
return versions;
List<ItemCollection> col = null;
String sRefID = workitem.getItemValueString("$workitemId");
String refQuery = "( (type:\"workitem\" OR type:\"workitemarchive\" OR type:\"workitemversion\") AND $workitemid:\""
+ sRefID + "\")";
try {
col = documentService.findStubs(refQuery, 999, 0, WorkflowKernel.LASTEVENTDATE, true);
// sort by $modified
Collections.sort(col, new ItemCollectionComparator("$modified", true));
// Only return version list if more than one version was found!
if (col.size() > 1) {
for (ItemCollection aworkitem : col) {
versions.add(aworkitem);
}
}
} catch (QueryException e) {
logger.warning("findAllVersions - invalid query: " + e.getMessage());
}
return versions;
}
}

View file

@ -1,175 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.ai.rag.index.IndexService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.WorkflowKernel;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.exceptions.QueryException;
import jakarta.inject.Inject;
/**
* The OrderPlugin is a generic plugin for Order workflows.
* <p>
* The plugin collects a list of $uniqueids for the last 5 orders for the given
* customer.ref. The list is stored in the item `order.history.ref`
*
* <p>
* The plugin extends the default imixs-ai RAGIndexPlugin. In the mode INDEX
* this plugins generates a default prompt template.This is to simplify the
* models.
* <p>
*
* <pre>
{@code
<dynamixs-ai name="INDEX">
<debug>false</debug>
</dynamixs-ai>
}
* </pre>
* <p>
* The tag 'debug' is optional
*
*
* @author rsoika
*
*/
public class OrderPlugin extends org.imixs.ai.rag.workflow.RAGIndexPlugin {
private static final Logger logger = Logger.getLogger(OrderPlugin.class.getName());
public static final String LINK_PROPERTY = "$workitemref";
public static final int MAX_HISTORY_RESULT = 5;
@Inject
private WorkflowService workflowService;
@Inject
private IndexService ragService;
@Override
public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException {
// do not run on Snapshots!
if (workitem.getType().startsWith("snapshot-")) {
// no op!
return workitem;
}
logger.info("├── running Dynamixs.AI Order Plugin");
// Update History....
updateOrderHistory(workitem);
// read optional configuration form the model or imixs.properties....
List<ItemCollection> ragIndexDefinitions = workflowService.evalWorkflowResultXML(event, "dynamixs-ai",
IndexService.RAG_INDEX, workitem, false);
try {
// INDEX Mode?
if (ragIndexDefinitions != null && ragIndexDefinitions.size() > 0) {
// do we have a prompt template?
ItemCollection indexDefinition = ragIndexDefinitions.get(0);
String promptTemplate = indexDefinition.getItemValueString("promptTemplate");
if (promptTemplate.isBlank()) {
// generate default template
ChronicleTextBuilder chronicleTextBuilder = new ChronicleTextBuilder(workitem);
promptTemplate = chronicleTextBuilder.build();
workitem.setItemValue("ai.chronicle.summary", promptTemplate);
indexDefinition.setItemValue("promptTemplate", embedTemplate(promptTemplate));
loadPromptDefinition(indexDefinition, event);
ragService.indexWorkitem(indexDefinition, workitem);
}
}
} catch (AdapterException e) {
throw new PluginException(e);
}
return workitem;
}
/**
* This method updates the item `order.history.ref` with the latest 5 orders for
* the current customer
*
* @param workitem
*/
private void updateOrderHistory(ItemCollection workitem) {
workitem.removeItem("order.history.ref");
String customerRef = workitem.getItemValueString("customer.ref");
if (!customerRef.isEmpty()) {
// append customer ref to $workitemref
workitem.appendItemValueUnique("$workitemref", customerRef);
// collect all history orders....
String sQuery = "(";
sQuery = " (type:\"workitem\" OR type:\"workitemarchive\") AND (" + LINK_PROPERTY + ":\"" + customerRef
+ "\") AND ($workflowgroup:\"" + workitem.getWorkflowGroup() + "\")";
List<ItemCollection> orderHistory = null;
try {
orderHistory = workflowService.getDocumentService().findStubs(sQuery, MAX_HISTORY_RESULT, 0,
WorkflowKernel.LASTEVENTDATE, true);
} catch (QueryException e) {
e.printStackTrace();
}
if (orderHistory != null) {
List<String> orderHistoryRefList = new ArrayList<>();
for (ItemCollection order : orderHistory) {
if (!workitem.getUniqueID().equals(order.getUniqueID())) { // skip current id!
orderHistoryRefList.add(order.getUniqueID());
}
}
workitem.setItemValue("order.history.ref", orderHistoryRefList);
}
}
}
/**
* Embedds a prompt into a imixs prompt template
*
*
* @param prompt
* @return
*/
private String embedTemplate(String prompt) {
String template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<PromptDefinition>\n" + //
" <prompt_options>{}</prompt_options>\n" + //
" <prompt><![CDATA[";
template = template + prompt;
template = template + "]]>\n" + //
"</prompt>\n" + //
"</PromptDefinition> ";
return template;
}
}

View file

@ -1,171 +0,0 @@
package ai.dynamixs.agent;
import java.io.Serializable;
import java.util.logging.Logger;
import org.imixs.ai.ImixsAIContextHandler;
import org.imixs.ai.workflow.ImixsAIToolCallEvent;
import org.imixs.ai.workflow.OpenAIAPIService;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.imixs.workflow.faces.data.WorkflowController;
import jakarta.enterprise.context.SessionScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.event.Reception;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Named("aiAgentController")
@SessionScoped
public class AIAgentController implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(AIAgentController.class.getName());
@Inject
private OpenAIAPIService openAIAPIService;
@Inject
private ImixsAIContextHandler contextHandler;
@Inject
protected WorkflowController workflowController;
@Inject
protected SkillController skillController;
private String userMessage;
private String agentResponse;
private String redirectUrl;
private static final int MAX_ITERATIONS = 10; // prevent infinite loops
/**
* Starts the conversation scope and initializes the context.
*/
public void init() {
logger.info("├── Initialize AI Agent");
redirectUrl = null;
agentResponse = null;
contextHandler.init();
// Build system prompt with skill headers
try {
contextHandler.addSystemMessage(
"You are a workflow assistant in Imixs-Office-Workflow. " +
"When a user wants to start a process, call start_process with the " +
"matching modelversion and taskId from the list below.\n\n" +
"Do NOT explain what you are doing. Just call the tool directly.\n\n" +
skillController.getSkillHeaders());
// Register start_process function
contextHandler.addFunction(
"start_process",
"Starts a BPMN workflow process for the user",
"""
{
"type": "object",
"properties": {
"$modelversion": {
"type": "string",
"description": "The model version of the process"
},
"$taskid": {
"type": "integer",
"description": "The task ID of the initial task"
},
"process.ref": {
"type": "string",
"description": "The unique ID referring of the process"
}
},
"required": ["$modelversion", "$taskid", "process.ref"]
}
""");
} catch (PluginException e) {
logger.warning("Failed to init AIAgent: " + e.getMessage());
}
}
/**
* Main entry point for the frontend. Runs the agent loop and returns either a
* text response or a redirect URL.
*/
public String startChat() throws PluginException {
init();
logger.info("├── Starting new chat");
logger.info("│ ├── User Question: " + userMessage);
contextHandler.addQuestion(userMessage, null, null);
// Agent Loop
int iterations = 0;
while (iterations < MAX_ITERATIONS) {
iterations++;
String response = openAIAPIService.postPromptCompletion(
contextHandler, null, true);
// Tool call? → processToolCallResult handles CDI events
boolean wasToolCall = openAIAPIService.processToolCallResult(
response, contextHandler);
if (!wasToolCall) {
// Normal text response → done
agentResponse = openAIAPIService.processPromptResult(
response, null, null);
return null; // stay on current page
}
// Check if a tool call produced a redirect URL
if (redirectUrl != null) {
return redirectUrl; // JSF redirect
}
}
throw new PluginException(AIAgentController.class.getSimpleName(),
"AGENT_LOOP_ERROR", "Max iterations reached!");
}
public void onToolCall(@Observes(notifyObserver = Reception.IF_EXISTS) ImixsAIToolCallEvent event)
throws PluginException {
try {
if ("start_process".equals(event.getToolName())) {
String modelVersion = event.getArguments().getString("$modelversion");
int taskId = event.getArguments().getInt("$taskid");
String processRef = event.getArguments().getString("process.ref");
workflowController.create(modelVersion, taskId, processRef);
// Set redirect URL directly on this bean - startChat() will pick it up
this.redirectUrl = "/pages/workitems/workitem.xhtml?id="
+ workflowController.getWorkitem().getUniqueID()
+ "&faces-redirect=true";
event.setResult("New Process started: " + workflowController.getWorkitem().getUniqueID());
}
} catch (ModelException e) {
throw new PluginException(e.getErrorContext(), e.getErrorCode(), e.getMessage());
}
}
public void setRedirectUrl(String url) {
this.redirectUrl = url;
}
public String getUserMessage() {
return userMessage;
}
public void setUserMessage(String userMessage) {
this.userMessage = userMessage;
}
public String getAgentResponse() {
return agentResponse;
}
}

View file

@ -1,155 +0,0 @@
package ai.dynamixs.agent;
import java.util.regex.Pattern;
/**
* Utility class to convert HTML content into clean, LLM-friendly markup text.
*/
public class HtmlStripper {
// Precompiled patterns for performance
private static final Pattern P_SCRIPT_STYLE = Pattern.compile(
"<(script|style)[^>]*>[\\s\\S]*?</\\1>", Pattern.CASE_INSENSITIVE);
private static final Pattern P_HEADING = Pattern.compile(
"<h[1-5][^>]*>(.*?)</h[1-5]>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
private static final Pattern P_STRONG = Pattern.compile(
"<(strong|b)[^>]*>(.*?)</(strong|b)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
private static final Pattern P_EM = Pattern.compile(
"<(em|i)[^>]*>(.*?)</(em|i)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
private static final Pattern P_LI = Pattern.compile(
"<li[^>]*>(.*?)</li>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
private static final Pattern P_BLOCK = Pattern.compile(
"<(p|div|br|tr|blockquote|pre|ul|ol|table)[^>]*/?>",
Pattern.CASE_INSENSITIVE);
private static final Pattern P_CLOSE_BLOCK = Pattern.compile(
"</(p|div|tr|blockquote|pre|ul|ol|table)>",
Pattern.CASE_INSENSITIVE);
private static final Pattern P_TAGS = Pattern.compile("<[^>]+>");
private static final Pattern P_MULTI_NEWLINE = Pattern.compile("\\n{3,}");
private static final Pattern P_BLANK_LINE = Pattern.compile("(?m)^[ \\t]+$");
/**
* Converts an HTML string into clean, LLM-readable markdown-style text. Handles
* headings, bold/italic, lists, images, HTML entities and removes all remaining
* tags. Designed to be minimal and allocation-efficient.
*
* @param content raw HTML input (may be null)
* @return clean markup text, or empty string if input is null/blank
*/
public static String stripHtml(String content) {
if (content == null || content.isBlank()) {
return "";
}
String s = content;
// 1. Normalize line endings
s = s.replace("\r\n", "\n").replace("\r", "\n");
// 2. Remove script / style blocks entirely
s = P_SCRIPT_STYLE.matcher(s).replaceAll("");
// 3. Images → [Image: alt] or drop silently
// s = P_IMG.matcher(s).replaceAll("[Image: $1]");
// s = P_IMG_NO_ALT.matcher(s).replaceAll("");
// 4. Headings → Markdown headings
s = P_HEADING.matcher(s).replaceAll("\n**$1**\n");
// 5. Bold / Italic → Markdown
s = P_STRONG.matcher(s).replaceAll("**$2**");
s = P_EM.matcher(s).replaceAll("*$2*");
// 6. List items → Markdown bullets
s = P_LI.matcher(s).replaceAll("\n- $1");
// 7. Block-level elements → newlines
s = P_BLOCK.matcher(s).replaceAll("\n");
s = P_CLOSE_BLOCK.matcher(s).replaceAll("\n");
// 8. Strip all remaining tags
s = P_TAGS.matcher(s).replaceAll("");
// 9. Decode HTML entities
s = decodeEntities(s);
// 10. Clean up whitespace
s = P_BLANK_LINE.matcher(s).replaceAll("");
s = P_MULTI_NEWLINE.matcher(s).replaceAll("\n\n");
return s.strip();
}
/**
* Decodes common named and numeric HTML entities. Covers the full ISO-8859-1 /
* HTML4 named entity set plus numeric references.
*/
private static String decodeEntities(String s) {
// Use a simple regex-replace loop for correctness
s = decodeNumericEntities(s);
// Named entities – most frequent ones in German/English business docs
s = s
.replace("&nbsp;", " ")
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&quot;", "\"")
.replace("&apos;", "'")
.replace("&auml;", "ä").replace("&Auml;", "Ä")
.replace("&ouml;", "ö").replace("&Ouml;", "Ö")
.replace("&uuml;", "ü").replace("&Uuml;", "Ü")
.replace("&szlig;", "ß")
.replace("&eacute;", "é").replace("&Eacute;", "É")
.replace("&egrave;", "è").replace("&Egrave;", "È")
.replace("&ecirc;", "ê").replace("&Ecirc;", "Ê")
.replace("&agrave;", "à").replace("&Agrave;", "À")
.replace("&acirc;", "â").replace("&Acirc;", "Â")
.replace("&ocirc;", "ô").replace("&Ocirc;", "Ô")
.replace("&ucirc;", "û").replace("&Ucirc;", "Û")
.replace("&ccedil;", "ç").replace("&Ccedil;", "Ç")
.replace("&ntilde;", "ñ").replace("&Ntilde;", "Ñ")
.replace("&copy;", "©")
.replace("&reg;", "®")
.replace("&trade;", "™")
.replace("&mdash;", "—")
.replace("&ndash;", "–")
.replace("&hellip;", "…")
.replace("&laquo;", "«").replace("&raquo;", "»")
.replace("&bull;", "•")
.replace("&euro;", "€");
return s;
}
private static final Pattern P_DEC_ENTITY = Pattern.compile("&#(\\d+);");
private static final Pattern P_HEX_ENTITY = Pattern.compile("&#x([0-9a-fA-F]+);");
/**
* Replaces numeric HTML entities (decimal and hex) with their Unicode
* characters.
*/
private static String decodeNumericEntities(String s) {
// Hex
var m = P_HEX_ENTITY.matcher(s);
var sb = new StringBuilder(); // ← StringBuilder statt StringBuffer
while (m.find()) {
int cp = Integer.parseInt(m.group(1), 16);
m.appendReplacement(sb, new String(Character.toChars(cp)));
}
m.appendTail(sb);
s = sb.toString();
// Decimal
m = P_DEC_ENTITY.matcher(s);
sb = new StringBuilder(); // ← StringBuilder
while (m.find()) {
int cp = Integer.parseInt(m.group(1));
m.appendReplacement(sb, new String(Character.toChars(cp)));
}
m.appendTail(sb);
return sb.toString();
}
}

View file

@ -1,160 +0,0 @@
/*******************************************************************************
* Imixs Workflow
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Project:
* http://www.imixs.org
* http://java.net/projects/imixs-workflow
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika - Software Developer
*******************************************************************************/
package ai.dynamixs.agent;
import java.io.Serializable;
import java.util.List;
import org.imixs.marty.team.TeamController;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.DocumentEvent;
import org.imixs.workflow.office.model.ModelController;
import jakarta.annotation.Resource;
import jakarta.ejb.SessionContext;
import jakarta.enterprise.context.SessionScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
/**
* The SkillController is a CDI bean handling workflow skills from the current
* process models.
*
* @author rsoika
*/
@SessionScoped
public class SkillController implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
TeamController teamController;
@Inject
ModelController modelController;
@Resource
SessionContext ctx;
String skillHeaders = null;
/**
* This method refreshes the cache of skillHeaders
*
* @param event
*/
public void onDocumentEvent(@Observes DocumentEvent event) {
String type = event.getDocument().getType();
if ((type.startsWith("process") || type.startsWith("model"))
&& (event.getEventType() == DocumentEvent.ON_DOCUMENT_SAVE
|| event.getEventType() == DocumentEvent.ON_DOCUMENT_DELETE)) {
skillHeaders = null;
}
}
/**
* Return the current skill headers. The method supports a lazy loading
* mechanism.
*
* @return
*/
public String getSkillHeaders() {
loadSkillHeaders();
return skillHeaders;
}
/**
* Helper method to load the skill headers for all available processes and
* assigned workflows
*
* @return
*/
private void loadSkillHeaders() {
if (skillHeaders == null) {
StringBuilder skillHeaderBuilder = new StringBuilder();
skillHeaderBuilder.append("Available Workflow Processes:\n\n");
List<ItemCollection> processList = teamController.getProcessList();
for (ItemCollection process : processList) {
if (process.getTaskID() == 301 || teamController.isManagerOf(process.getUniqueID())) {
String processName = process.getItemValueString("name");
String processDescription = HtmlStripper
.stripHtml(process.getItemValueString("txtdescription"));
List<String> workflowList = process.getItemValueList("txtWorkflowList", String.class);
// Collect workflow entries first - skip process if none found
StringBuilder workflowEntries = new StringBuilder();
for (String group : workflowList) {
String modelVersion = modelController.getVersionByGroup(group);
List<ItemCollection> startTasks = modelController.findAllStartTasksByGroup(modelVersion, group);
if (!startTasks.isEmpty()) {
ItemCollection initialTask = startTasks.get(0);
int taskId = initialTask.getItemValueInteger("taskid");
String taskDescription = HtmlStripper.stripHtml(
modelController.getProcessDescriptionByInitialTask(initialTask, modelVersion,
group));
workflowEntries.append("- ").append(group).append(": ");
if (taskDescription != null && !taskDescription.isBlank()) {
workflowEntries.append(taskDescription);
} else if (processDescription != null && !processDescription.isBlank()) {
workflowEntries.append(processDescription);
}
workflowEntries.append(" (model: ").append(modelVersion)
.append(", taskid: ").append(taskId)
.append(", process.ref: ").append(process.getUniqueID())
.append(")\n");
}
}
// Only add process section if it has at least one workflow
if (workflowEntries.length() > 0) {
skillHeaderBuilder.append("[").append(processName).append("]");
if (processDescription != null && !processDescription.isBlank()) {
skillHeaderBuilder.append(" - ").append(processDescription);
}
skillHeaderBuilder.append("\n");
skillHeaderBuilder.append(workflowEntries);
skillHeaderBuilder.append("\n");
}
}
}
skillHeaders = skillHeaderBuilder.toString();
}
}
}

View file

@ -1,2 +0,0 @@
Manifest-Version: 1.0

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<!--
Imixs JPA definition Make sure that the imixs-workflow-jee library
version maches the version provided by the EAR/EJB
-->
<!-- eclipselink -->
<persistence-unit name="org.imixs.workflow.jpa" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>${imixs-office.jta-data-source}</jta-data-source>
<jar-file>lib/imixs-workflow-engine-${org.imixs.workflow.version}.jar</jar-file>
<jar-file>lib/imixs-marty-${org.imixs.marty.version}.jar</jar-file>
<properties>
<!-- target-database Auto MySQL PostgreSQL -->
<property name="eclipselink.target-database" value="Auto" />
<property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
<property name="eclipselink.deploy-on-startup" value="true" />
<property name="eclipselink.logging.level" value="INFO" />
</properties>
</persistence-unit>
</persistence>

View file

@ -1,7 +0,0 @@
# Build Information
build.version=${project.version}
build.timestamp=${org.imixs.build.timestamp}
build.office.version=${org.imixs.office.version}
build.marty.version=${org.imixs.marty.version}
build.workflow.version=${org.imixs.workflow.version}
build.name=${imixs-office.applicationname}

View file

@ -1,45 +0,0 @@
##############################
# Imixs-Workflow
##############################
model.default.data=system-de-1.3.0.bpmn
lucence.indexDir=${imixs-office.IndexDir}
index.fields=txtsearchstring,txtSubject,txtname,txtEmail,txtUserName,namCreator,txtworkflowgroup,txtworkflowstatus,txtWorkflowAbstract,txtWorkflowSummary,txtworkflowhistory,txtspacename,txtprocessname,_subject,_description,_name,_projectnumber,_projectname,_ordernumber,_contractnumber,datDueDate,txtcommentlog,htmldescription,htmldocumentation,_childitems
index.fields.analyze=txtUsername
index.fields.noanalyze=type,$UniqueIDRef,$created,$modified,$ModelVersion,namCreator,$ProcessID,datDate,txtWorkflowGroup,txtemail, datdate, datfrom, datto, numsequencenumber,dms_count,
index.fields.store=process.name,txtProcessName,txtWorkflowImageURL
index.fields.category=space.name,space.ref
##############################
# Model Setup
##############################
setup.system.model=system-de-1.3
# Office Properties
BASIC.maxviewentries=10
##############################
# Marty Security
##############################
security.setup.mode=auto
security.userid.input.mode=LOWERCASE
security.email.unique=true
#security.userid.input.pattern=
# Profile - autoprocess event
profile.login.event=100
# Marty Mail Plugin
# mail.defaultSender=info@imixs.com
# Image reziser
image.fileExtension=jpg,gif
image.maxWidth=2048
dms.search=true

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
bean-discovery-mode="all" version="3.0">
</beans>

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>

View file

@ -1,146 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<display-name>imixs-office-workflow</display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- -->
<context-param>
<param-name>jakarta.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>jakarta.faces.CONFIG_FILES</param-name>
<param-value>
/WEB-INF/faces-config-office.xml,
/WEB-INF/faces-config-custom.xml
</param-value>
</context-param>
<!-- project stage is computed by the maven profile settings -->
<context-param>
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<!-- Session Timeout 180 = 3h -->
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<!-- Facelets -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
<multipart-config>
<location>/tmp</location>
<!-- 20MB (20848820) *2MB (2097152)-->
<max-file-size>2097152</max-file-size>
<!-- 400MB (418018841) *20MB (20848820)-->
<max-request-size>20848820</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Error handling -->
<error-page>
<error-code>401</error-code>
<location>/loginerror.jsf</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/authorizationerror.html</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.jsf</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsf</location>
</error-page>
<!-- Login Modul - Form-Login -->
<login-config>
<auth-method>FORM</auth-method>
<realm-name>imixsrealm</realm-name>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/loginerror.jsf</form-error-page>
</form-login-config>
</login-config>
<!-- Wildfly OIDC Login Module
Note: WEB-INF/oidc.yaml file is mandatory!
<login-config>
<auth-method>OIDC</auth-method>
</login-config>
-->
<!-- Security Roles -->
<security-constraint>
<display-name>Access Manager Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>AUTHENTICATED_RESOURCE</web-resource-name>
<url-pattern>/pages/*</url-pattern>
<url-pattern>/api/workflow/*</url-pattern>
<url-pattern>/api/model/*</url-pattern>
<url-pattern>/api/documents/*</url-pattern>
<url-pattern>/api/report/*</url-pattern>
<url-pattern>/api/snapshot/*</url-pattern>
<url-pattern>/api/adminp/*</url-pattern>
<url-pattern>/api/eventlog/*</url-pattern>
<url-pattern>/api/logout</url-pattern>
<!-- exclude /api/metrics and /api/wopi -->
</web-resource-collection>
<auth-constraint>
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>AUTHENTICATED_ADMIN_RESOURCE</web-resource-name>
<url-pattern>/pages/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>org.imixs.ACCESSLEVEL.NOACCESS</role-name>
</security-role>
<security-role>
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
</security-role>
<security-role>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
</security-role>
<security-role>
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
</security-role>
<security-role>
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
</security-role>
</web-app>

View file

@ -1,63 +0,0 @@
// custom scripts
/**
* This method renders $workflowabstarct as markup
*/
$(document).ready(function() {
});
function showTooltip(trigger) {
const tooltip = trigger.nextElementSibling;
const rect = trigger.getBoundingClientRect();
// Position relativ zum Viewport berechnen
tooltip.style.left = rect.left + 'px';
tooltip.style.top = (rect.bottom + 5) + 'px';
// Markdown nur einmal parsen (lazy loading)
const markdownContainer = tooltip.querySelector('.imixs-workflowabstract');
if (markdownContainer && !markdownContainer.dataset.parsed) {
const rawMarkdown = markdownContainer.textContent;
markdownContainer.innerHTML = marked.parse(rawMarkdown);
markdownContainer.dataset.parsed = 'true'; // Flag setzen
}
tooltip.classList.add('visible');
// Optional: Prüfen ob Tooltip aus dem Viewport ragt
const tooltipRect = tooltip.getBoundingClientRect();
if (tooltipRect.right > window.innerWidth) {
tooltip.style.left = (window.innerWidth - tooltipRect.width - 10) + 'px';
}
if (tooltipRect.bottom > window.innerHeight) {
tooltip.style.top = (rect.top - tooltipRect.height - 5) + 'px';
}
}
function hideTooltip(trigger) {
const tooltip = trigger.nextElementSibling;
tooltip.classList.remove('visible');
}
/**
* Helper method to trigger the workflowabstract element in the form
* @param {} trigger
*/
function toggleWorkflowAbstract(trigger) {
const content = trigger.nextElementSibling;
// Markdown nur einmal parsen (lazy loading)
const markdownContainer = content.querySelector('.imixs-markdown-output');
if (markdownContainer && !markdownContainer.dataset.parsed) {
const rawMarkdown = markdownContainer.textContent;
markdownContainer.innerHTML = marked.parse(rawMarkdown);
markdownContainer.dataset.parsed = 'true';
}
content.classList.toggle('hidden');
}

View file

@ -1,15 +0,0 @@
<f:subview xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ul>
<li><h:link outcome="/pages/admin/document_import">Dokument Import</h:link></li>
<!-- SEPA -->
<li><h:link outcome="/pages/admin/sepa_config">SEPA</h:link></li>
<li><h:link outcome="/pages/admin/datev_config">DATEV</h:link></li>
</ul>
</f:subview>

View file

@ -1,116 +0,0 @@
/* --- Custom Layout --- */
#imixs-header {
background-color: #599191;
}
#imixs-branding {
background-color: #599191;
background-image: url("./logo-01.png");
background-repeat: no-repeat;
background-position: 10px 15px;
background-size: 140px;
min-height: 120px;
color: #fff;
}
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default, .ui-button, html .ui-button.ui-state-disabled:hover, html .ui-button.ui-state-disabled:active {
border: 1px solid #599191;
background: #599191;
}
.imixsfileupload input[type="file"] + label {
background-color: #599191;
}
.imixsfileupload input[type="file"] + label:hover {
background-color: #62a2a2;
}
.ui-button:hover {
background: #62a2a2;
}
.imixs-workitem-chronicle-tabs ul li.active a {
color: #599191;
}
.imixsdatatable th {
background: #599191;
color: #fff;
border-left: 4px solid #599191;
border-bottom: 1px solid #599191;
}
.imixs-llm, .imixs-llm:focus, .imixs-date.imixs-llm, .imixs-date.imixs-llm:focus {
border: none !important;
border-bottom: 2px solid #faa732 !important;
box-shadow: none !important;
text-align: left !important;
border-radius: 0;
background-color: transparent !important;
}
/* Neues Abstract markup */
.tooltip-container {
position: relative;
display: inline-block;
}
.tooltip-trigger {
cursor: pointer;
color: #007bff;
}
.tooltip-content {
display: none;
position: fixed;
font-size: 0.85rem;
line-height: 1.75;
left: 0;
top: 100%;
z-index: 1200;
background: white;
border: 1px solid #ccc;
border-radius: 4px;
min-width: 420px;
max-width: 650px;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
background-color: #ffffff;
padding: 10px;
transition: opacity 0.5s ease-in-out, visibility 0.3s ease-in-out;
}
.tooltip-container:hover .tooltip-content {
display: block;
}
.imixs-workflowabstract-toggle-icon {
margin-left: auto;
align-self: flex-end;
cursor: pointer;
padding: 10px;
font-size: 1.25rem;
color: #599191;
}
.imixs-workflowabstract-content {
flex-basis: 100%;
padding: 0 15px;
border: 1px solid #599191;
margin: 0 15px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,15 +0,0 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
<f:view>
<div class="toolbar agent">
<h:inputText a:data-id="nav_input_phrase" style="margin-right: 10px;" a:placeholder="What do you need?"
value="#{aiAgentController.userMessage}" />
<h:commandLink action="#{aiAgentController.startChat()}" a:data-id="nav_search_link"><span
class="typcn typcn-lightbulb" style="font-size:1.4em;"></span>
</h:commandLink>
</div>
</f:view>
</ui:composition>

View file

@ -1,79 +0,0 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions" xmlns:marty="http://xmlns.jcp.org/jsf/composite/marty"
xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
<!-- Build with link ? -->
<span class="imixs-icon tooltip-container" title=" ">
<span class="tooltip-trigger" onmouseenter="showTooltip(this)" onmouseleave="hideTooltip(this)">
<ui:fragment rendered="#{showlink}">
<h:link outcome="/pages/workitems/workitem">
<!-- typcn -->
<ui:fragment rendered="#{fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
<span class="imixs-typicon" data-typicon="#{workitem.item['txtWorkflowImageURL']}"></span>
</ui:fragment>
<!-- Image -->
<ui:fragment rendered="#{!fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
<h:graphicImage rendered="#{!empty workitem.item['txtWorkflowImageURL']}"
url="#{workitem.item['txtWorkflowImageURL']}" style="max-height: 24px; margin: 4px;">
</h:graphicImage>
<h:graphicImage rendered="#{empty workitem.item['txtWorkflowImageURL']}"
value="/layout/icons/vwicn070.png" style="max-height: 24px; margin: 4px;"></h:graphicImage>
</ui:fragment>
<f:param name="id" value="#{workitem.item['$uniqueid']}" />
</h:link>
</ui:fragment>
<!-- Build without link -->
<ui:fragment rendered="#{!showlink}">
<!-- typcn -->
<ui:fragment rendered="#{fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
<span class="imixs-typicon" data-typicon="#{workitem.item['txtWorkflowImageURL']}"></span>
</ui:fragment>
<!-- Image -->
<ui:fragment rendered="#{!fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
<h:graphicImage rendered="#{!empty workitem.item['txtWorkflowImageURL']}"
url="#{workitem.item['txtWorkflowImageURL']}" style="max-height: 24px; margin: 4px;">
</h:graphicImage>
<h:graphicImage rendered="#{empty workitem.item['txtWorkflowImageURL']}"
value="/layout/icons/vwicn070.png" style="max-height: 24px; margin: 4px;"></h:graphicImage>
</ui:fragment>
</ui:fragment>
</span>
<h:panelGroup class="tooltip-content">
<h:outputText value="#{message.created}: " style="font-weight:bold;" />
<h:outputText value="#{workitem.item['$created']}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both" pattern="#{message.dateTimePattern}" />
</h:outputText>
<h:outputText value=" #{message.by} #{userController.getUserName(workitem.item['$creator'])}" />
<!-- Modified -->
<br />
<span>
<h:outputText style="font-weight: bold;" value="#{message.edited}: " />
<h:outputText value="#{workitem.item['$lasteventdate']}" style="font-weight: normal;">
<f:convertDateTime timeZone="#{message.timeZone}" pattern="#{message.dateTimePattern}" />
</h:outputText>
<h:outputText value=" #{message.by} #{userController.getUserName(workitem.item['$editor'])}" />
</span>
<hr />
<!-- Markup -->
<div class="imixs-workflowabstract">
<h:outputText styleClass="imixs-markdown-output" value="#{workitem.item['$WorkflowAbstract']}"
escape="false" />
</div>
</h:panelGroup>
</span>
</ui:composition>

View file

@ -1,317 +0,0 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:i="http://java.sun.com/jsf/composite/imixs" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
xmlns:marty="http://java.sun.com/jsf/composite/marty" template="/layout/template.xhtml">
<ui:define name="content">
<f:view>
<script type="text/javascript">
/*<![CDATA[*/
$(document).ready(function () {
//$('.imixsdatatable').layoutImixsTable();
});
// This method refreshs the layout
function updateOptions(data) {
if (data.status === 'success') {
$('[id$=Optionlist]').imixsLayout();
/* var id='#'+data.source.id;
if (id.indexOf("input")>-1) {
$(id).focus();
} */
}
}
/*]]>*/
</script>
<h:form id="import_form_id">
<!-- ########## Error ########## -->
<ui:include src="/error_message.xhtml" />
<div class="imixs-form">
<div class="imixs-header">
<h1>Document Importer</h1>
</div>
<div class="imixs-body">
<div class="imixs-tabs">
<ul>
<li><a href="#tab-1">Timer Setting</a></li>
<li><a href="#tab-2">Data Sources</a></li>
</ul>
<!-- ### Timer ### -->
<div id="tab-1">
<div class="ui-state-highlight ui-corner-all"
style="margin-bottom: 10px; padding: .5em;">
<p><span class="typcn typcn-lightbulb"></span> Define a crontab to schedule the
import processor.</p>
</div>
<ui:include src="sub_scheduler_control.xhtml">
<ui:param name="schedulerController" value="#{documentImportController}" />
</ui:include>
</div>
<!-- ### SMTP ### -->
<div id="tab-2">
<div class="ui-state-highlight ui-corner-all"
style="margin-bottom: 10px; padding: .5em;">
<p><span class="typcn typcn-lightbulb"></span> Define a destination IMAP server and
assign mail addresses to specific workflow groups.</p>
</div>
<div class="imixs-form-panel">
<!-- ### Sources ### -->
<h:panelGroup layout="block" id="imapOptionlist"
binding="#{imapOptionlistContainer}">
<f:ajax onevent="updateOptions">
<table class="imixsdatatable" style="width: 100%;">
<thead>
<tr>
<th style="width: 10px;text-align: center;">Pos</th>
<th style="width: 100px;text-align: center;">Type</th>
<th style="">Workflowgroup</th>
<th style="">Modelversion</th>
<th style="">Task</th>
<th style="">Event</th>
<th style="width: 110px;">
<!-- delete -->
</th>
</tr>
</thead>
<tbody>
<ui:repeat var="source" value="#{documentImportController.sources}">
<tr>
<!-- pos -->
<td style=" text-align: center;">
<h:commandLink
actionListener="#{documentImportController.selectSource(source.item['index'])}">
#
<h:outputText value="#{source.item['index']}" />
<f:ajax render="#{imapOptionlistContainer.clientId}"
onevent="updateOptions" />
</h:commandLink>
</td>
<!-- type -->
<td style="text-align: center;">
<h:outputText value="#{source.item['type']}" />
</td>
<!-- Workflowgroup -->
<td>
<h:outputText value="#{source.item['workflowgroup']}" />
</td>
<td>
<h:outputText value="#{source.item['workflowmodel']}" />
</td>
<td>
<h:outputText value="#{source.item['task']}" />
</td>
<td>
<h:outputText value="#{source.item['event']}" />
</td>
<td>
<h:commandLink
actionListener="#{documentImportController.moveSourceDown(source.item['index'])}">
<span
class="typcn typcn-arrow-down-thick imixs-state-info"></span>
<f:ajax render="#{imapOptionlistContainer.clientId}"
onevent="updateOptions" />
</h:commandLink>
<h:commandLink
actionListener="#{documentImportController.moveSourceUp(source.item['index'])}">
<span
class="typcn typcn-arrow-up-thick imixs-state-info"></span>
<f:ajax render="#{imapOptionlistContainer.clientId}"
onevent="updateOptions" />
</h:commandLink>
<h:commandLink
actionListener="#{documentImportController.removeSource(source.item['index'])}">
<span
class="typcn typcn-trash imixs-state-info"></span>
<f:ajax render="#{imapOptionlistContainer.clientId}"
onevent="updateOptions" />
</h:commandLink>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
<!-- add button -->
<h:commandButton value="#{message.add}"
actionListener="#{documentImportController.addSource()}">
<f:ajax render="#{imapOptionlistContainer.clientId}"
onevent="updateOptions" />
</h:commandButton>
<!-- ### Subform for selected source ### -->
<h:panelGroup layout="block"
rendered="#{! empty documentImportController.source}"
styleClass="imixs-form-panel">
<h3>Order ID #
<h:outputText
value="#{documentImportController.source.item['index']}" />
</h3>
<div class="imixs-form-section-3">
<dl>
<dt>Type</dt>
<dd>
<h:selectOneRadio
value="#{documentImportController.source.item['type']}">
<f:selectItem itemLabel="IMAP" itemValue="IMAP" />
<f:selectItem itemLabel="FTP" itemValue="FTP" />
<f:selectItem itemLabel="CSV" itemValue="CSV" />
</h:selectOneRadio>
</dd>
</dl>
<dl>
<dt>Workflowgroup</dt>
<dd>
<h:selectOneMenu
value="#{documentImportController.source.item['workflowgroup']}">
<f:selectItem itemLabel=" - " itemValue="" />
<c:forEach items="#{modelController.workflowGroups}"
var="group">
<f:selectItem itemLabel="#{group}"
itemValue="#{group}" />
</c:forEach>
</h:selectOneMenu>
</dd>
</dl>
</div>
<div class="imixs-form-section-3">
<dl>
<dt>Workflowmodel</dt>
<dd>
<h:inputText
value="#{documentImportController.source.item['workflowmodel']}" />
</dd>
</dl>
<dl>
<dt>Task ID</dt>
<dd>
<h:inputText
value="#{documentImportController.source.item['task']}" />
</dd>
</dl>
<dl>
<dt>Event ID</dt>
<dd>
<h:inputText
value="#{documentImportController.source.item['event']}" />
</dd>
</dl>
</div>
<hr />
<!-- IMAP -->
<div class="imixs-form-section-3">
<dl>
<dt>Server : Port</dt>
<dd>
<h:inputText style="width:80%;"
value="#{documentImportController.source.item['server']}">
</h:inputText> : <h:inputText style="width:15%;"
value="#{documentImportController.source.item['port']}">
</h:inputText>
</dd>
</dl>
<dl>
<dt>User</dt>
<dd>
<h:inputText required="false"
value="#{documentImportController.source.item['user']}">
</h:inputText>
</dd>
</dl>
<dl>
<dt>Password</dt>
<dd>
<h:inputSecret required="false" redisplay="true"
value="#{documentImportController.source.item['password']}">
</h:inputSecret>
</dd>
</dl>
</div>
<div class="imixs-form-section">
<dl>
<dt>Selector</dt>
<dd>
<h:inputText required="false"
value="#{documentImportController.source.item['selector']}">
</h:inputText>
<p class="small">A selector can be an optional regular
expression to be used to select a subset of data</p>
</dd>
</dl>
<dl>
<dt>Options</dt>
<dd>
<h:inputTextarea required="false"
style="height: 5em; width: 100%;"
value="#{documentImportController.source.item['options']}">
</h:inputTextarea>
<p class="small">You can apply custom properties here.
</p>
</dd>
</dl>
</div>
</h:panelGroup> <!-- end of source subform -->
</f:ajax>
</h:panelGroup>
</div>
</div>
</div>
</div>
<div class="imixs-footer">
<h:outputLabel value="#{message.modified}: " />
<h:outputText value="#{documentImportController.configuration.item['$modified']}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePattern}" />
</h:outputText>
<br />
<h:commandButton actionListener="#{documentImportController.saveConfiguration()}"
action="/pages/admin/document_import" value="#{message.save}">
</h:commandButton>
<h:commandButton value="#{message.close}" action="notes" />
</div>
</div>
</h:form>
</f:view>
</ui:define>
</ui:composition>

View file

@ -1,100 +0,0 @@
<f:subview xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions">
<script type="text/javascript">
/*<![CDATA[*/
function updateStatustPanel(data) {
//initUserInput($('#userselector_id'));
if (data.status === 'success') {
$('[id$=status_panel]').imixsLayout();
}
}
/*]]>*/
</script>
<!-- **** General info ***** -->
<div class="imixs-form-panel">
<h:inputTextarea required="false" converter="org.imixs.VectorConverter" style="height: 8em; width: 100%;"
value="#{schedulerController.configuration.itemList['_scheduler_definition']}">
</h:inputTextarea>
</div>
<!-- **** Timer Status ***** -->
<h:panelGroup layout="block" class="imixs-form-panel" id="status_panel">
<h:panelGroup layout="block" id="timer_details" class="imixs-form-section">
<h2>
<h:outputText id="timer_status"
value="Status ⇢ #{schedulerController.configuration.item['_scheduler_status']}" />
<h:panelGroup rendered="#{! empty schedulerController.configuration.item['_scheduler_errormessage']}"
class="small" style="color:red">
<br />Error: #{schedulerController.configuration.item['_scheduler_errormessage']}
</h:panelGroup>
</h2>
<h:panelGrid columns="2">
<h:panelGroup layout="block" style="width:100px;">
<h:outputLabel value="ID: " />
</h:panelGroup>
<h:panelGroup>
<h:outputText value="#{schedulerController.configuration.item['$UniqueID']}" />
</h:panelGroup>
<h:outputLabel value="Schedule: " />
<h:outputText value="#{schedulerController.configuration.item['Schedule']}" />
<h:outputLabel value="Next Timeout: " />
<h:panelGroup>
<h:outputText value="#{schedulerController.configuration.item['nextTimeout']}"
rendered="#{! empty schedulerController.configuration.item['nextTimeout']}">
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
pattern="#{message.dateTimePattern}" />
</h:outputText>
<h:outputText value=" " />
</h:panelGroup>
<h:outputLabel value="TimeRemaining: " />
<h:outputText
value="#{schedulerController.millisToShortDHMS(schedulerController.configuration.item['timeRemaining'])}" />
</h:panelGrid>
<h:outputLabel value="Last Run: " />
<h:panelGroup layout="block" class="ui-state-highlight ui-corner-all"
style="padding: .5em;background: #f5f5f5;padding: 10px;height: 260px;overflow-y: auto;">
<ui:fragment rendered="#{! empty schedulerController.configuration.item['_scheduler_logmessage']}">
<pre style="font-family: 'Courier New', Courier, monospace;color: #111;line-height: 1.0rem;"> <ui:repeat var="logentry" value="#{schedulerController.configuration.itemList['_scheduler_logmessage']}">
<h:outputText escape="false" value="#{logentry}" /><br />
</ui:repeat></pre>
</ui:fragment>
<ui:fragment rendered="#{empty schedulerController.configuration.item['_scheduler_logmessage']}">
No Data.
</ui:fragment>
</h:panelGroup>
</h:panelGroup>
<!-- Timer Actions -->
<h:commandButton value="#{message.refresh}" actionListener="#{schedulerController.refresh}">
<f:ajax render="status_panel" onevent="updateStatustPanel" />
</h:commandButton>
<h:commandButton actionListener="#{schedulerController.startScheduler}" value="start">
</h:commandButton>
<h:commandButton actionListener="#{schedulerController.stopScheduler}" value="stop">
</h:commandButton>
<h:commandButton actionListener="#{schedulerController.restartScheduler}" value="restart">
</h:commandButton>
</h:panelGroup>
</f:subview>

View file

@ -1,107 +0,0 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:marty="http://xmlns.jcp.org/jsf/composite/marty" xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
<div style="display: flex;">
<div style="flex:1;">
<h1>
<h:outputText value="#{workflowController.workitem.item['$workflowgroup']}" />
»
<h:outputText value=" #{workflowController.workitem.item['$workflowstatus']}" />
<!-- Display Deleted status -->
<h:outputText rendered="#{workflowController.workitem.item['type'] eq 'workitemdeleted'}"
value="- #{message.deleted}!" style="color:red;" />
</h1>
<!-- Workitem Info Header -->
<div class="imixs-form-header">
<!-- *** Image *** -->
<div class="image-block">
<ui:include src="/layout/workitem_icon.xhtml">
<ui:param name="workitem" value="#{workflowController.workitem}" />
<ui:param name="hidetooltip" value="#{true}" />
</ui:include>
</div>
<ui:remove><!-- *** Standard Info *** --></ui:remove>
<div class="content-block">
<h2>
<h:outputText escape="false"
rendered="#{empty workflowController.workitem.item['$WorkflowSummary']}"
value="#{message.new_workitem}" />
<h:outputText escape="false"
rendered="#{!empty workflowController.workitem.item['$WorkflowSummary']}"
value="#{workflowController.workitem.item['$WorkflowSummary']}" />
</h2>
<h:outputLabel value="#{message['process.title']}: " />
<h:link outcome="/pages/notes_board?processref=#{workflowController.workitem.item['process.Ref']}">
<h:outputText value="#{workflowController.workitem.item['Process.Name']}" />
</h:link>
<ui:remove><!-- *** Owners *** --></ui:remove>
<h:panelGroup styleClass="imixs-no-print" layout="block">
<ui:repeat value="#{workflowController.workitem.itemList['$owner']}" var="name">
<ui:param name="profile" value="#{userController.getProfile(name)}"></ui:param>
<ui:fragment rendered="#{! empty profile}">
<h:graphicImage styleClass="imixs-workitem-chronicle-usericon"
title="#{profile.item['txtusername']}"
rendered="#{! empty profile.item['txtusericon']}"
value="/api/snapshot/#{profile.item['$uniqueid']}/file/#{profile.item['txtusericon']}">
</h:graphicImage>
<!-- optional - user initials -->
<h:panelGroup layout="block" rendered="#{empty profile.item['txtusericon']}">
<h:outputText styleClass="imixs-workitem-chronicle-usericon"
title="#{profile.item['txtusername']}" value="#{profile.item['txtinitials']}" />
</h:panelGroup>
</ui:fragment>
</ui:repeat>
</h:panelGroup>
</div>
<!-- *** Comment Toggle *** -->
<div class="imixs-workflowabstract-toggle-icon" onclick="toggleWorkflowAbstract(this)">
<i class="fa-regular fa-comment-dots"></i>
</div>
<!-- Extra Content - volle Breite -->
<div class="imixs-workflowabstract-content hidden">
<h:outputText styleClass="imixs-markdown-output"
rendered="#{workflowController.workitem.taskID eq 1210}"
value="#{indexController.getContent(workflowController.workitem.uniqueID, 'CSDDD')}"
escape="false" />
<h:outputText styleClass="imixs-markdown-output"
rendered="#{workflowController.workitem.taskID ne 1210}"
value="#{indexController.getContent(workflowController.workitem.uniqueID, '')}"
escape="false" />
</div>
</div>
</div>
<!-- QR-Code displayed only if property 'qr-code.url.prafix' is filled -->
<ui:param name=" qrprafix" value="#{propertyController.getProperty('qr-code.url.prafix')}">
</ui:param>
<ui:fragment
rendered="#{(! empty workflowController.workitem.uniqueID) and (!userController.mobileUser) and (!empty qrprafix)}">
<div style="flex-grow: 1;"></div>
<div>
<a href="#" onclick="imixsOfficeWorkitem.printQRCode();">
<h:graphicImage styleClass="imixsQrCode"
url="/api/qr-code?size=130&amp;key=#{qrprafix}#{workflowController.workitem.uniqueID}">
</h:graphicImage>
</a>
</div>
</ui:fragment>
</div>
</ui:composition>

View file

@ -1,140 +0,0 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs.agent;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Optional;
import org.imixs.ai.ImixsAIContextHandler;
import org.imixs.ai.workflow.OpenAIAPIConnector;
import org.imixs.ai.workflow.OpenAIAPIService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
/**
* Test class to test a function call
*
*
* @author rsoika
*/
@ExtendWith(MockitoExtension.class)
public class TestAgentCall {
private static final String MISTRAL_ENDPOINT = "https://api.llama.cpp.imixs.com/";
public static final String MISTRAL_API_KEY = "7fdb663fa87ea16731c1e0ece8ad3214e358423eabf2403188110c731ce07321";
private OpenAIAPIService service;
private OpenAIAPIConnector connector;
@BeforeEach
void setUp() throws Exception {
connector = new OpenAIAPIConnector();
connector.setServiceEndpointApiKey(Optional.of(MISTRAL_API_KEY));
connector.setServiceEndpointUser(Optional.empty());
connector.setServiceEndpointPassword(Optional.empty());
injectField(connector, "serviceTimeout", 30000);
injectField(connector, "serviceEndpoint", Optional.of(MISTRAL_ENDPOINT));
service = new OpenAIAPIService();
injectField(service, "openAIAPIConnector", connector);
}
@Test
void testHelloWorld() throws Exception {
// Build a simple "Hello World" prompt
ImixsAIContextHandler contextHandler = new ImixsAIContextHandler();
contextHandler.addQuestion("Say hello world!", null, null);
String response = service.postPromptCompletion(contextHandler, MISTRAL_ENDPOINT, true);
assertNotNull(response);
System.out.println("Response: " + response);
}
@Test
void testFunctionCalling() throws Exception {
ImixsAIContextHandler contextHandler = new ImixsAIContextHandler();
// Define system context
contextHandler.addSystemMessage("""
You are a workflow assistant integrated into the Imixs-Office-Workflow suite.
The following BPMN processes are available:
- urlaubsantrag: Vacation request process
- reisekostenabrechnung: Travel expense process
- eingangsrechnung: Incoming invoice process
When a user wants to start a process, always call the load_skill tool
with the matching process_id. Never ask the user for the process ID.
""");
// Define the load_skill function
contextHandler.addFunction(
"load_skill",
"Loads details about an available BPMN workflow process",
"""
{
"type": "object",
"properties": {
"process_id": {
"type": "string",
"description": "The ID of the BPMN process, e.g. urlaubsantrag"
}
},
"required": ["process_id"]
}
""");
contextHandler.addQuestion(
"I need next week off. Can you start the vacation request process?",
"tom.clancy", new Date());
// Print the full request JSON to verify it looks correct
System.out.println("Request: " + contextHandler.toString());
String response = service.postPromptCompletion(contextHandler, MISTRAL_ENDPOINT, true);
assertNotNull(response);
System.out.println("Response: " + response);
// Check if Mistral responded with a tool call
assertTrue(response.contains("load_skill"),
"Expected Mistral to call load_skill tool");
// Verify Mistral responded with a tool call
assertTrue(response.contains("\"finish_reason\":\"tool_calls\""));
assertTrue(response.contains("\"name\":\"load_skill\""));
assertTrue(response.contains("urlaubsantrag"));
}
private void injectField(Object target, String fieldName, Object value) throws Exception {
Class<?> clazz = target.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
return;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(fieldName);
}
}

View file

@ -1,583 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowmodelversion" type="xs:string">
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
</imixs:item>
<imixs:item name="txtfieldmapping" type="xs:string">
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
</imixs:item>
<imixs:item name="txttimefieldmapping" type="xs:string">
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
</imixs:item>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
<bpmn2:documentation id="documentation_3xKpCQ"/>
</bpmn2:participant>
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
</bpmn2:collaboration>
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane_1" name="Team">
<bpmn2:documentation id="documentation_gvQWYQ"/>
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_yrC2dw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_J0JjAg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_1FAZgA</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_cjoSqg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>gateway_SVo89A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_5P6uhg</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_5RftUw" name="Contract Management">
<bpmn2:documentation id="documentation_AW2roA"/>
<bpmn2:flowNodeRef>task_0W5Llw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_0k30Ug</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_vJ0eNA</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_a0dlhQ" name="Contract Owner">
<bpmn2:documentation id="documentation_fATy7A"/>
<bpmn2:flowNodeRef>task_GgAr6w</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_zpkT5A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_v7oUjw</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_A6bDCA" name="Sales">
<bpmn2:documentation id="documentation_l0BSxA"/>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="StartEvent_1" name="Start">
<bpmn2:documentation id="documentation_IUTaAQ"/>
<bpmn2:outgoing>sequenceFlow_mCJiSA</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:endEvent id="EndEvent_2" name="End">
<bpmn2:documentation id="documentation_mHDfBQ"/>
</bpmn2:endEvent>
<bpmn2:task id="task_yrC2dw" imixs:processid="2100" name="Contract Creation">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_BN3NHA"><![CDATA[Erstellung eines neuen Vertrags mit folgenden Pflichtfeldern: - **Vertragspartner** (Name, Adresse, Kontaktdaten, Vertragsnummer) - **Waren/Lieferungen** (Beschreibung, Menge, Einheit, Preis pro Einheit, Gesamtpreis, ggf. SKU/Artikelnummer) - **Lagerort** (falls relevant: Lagerstandort, Lagerverantwortlicher) - **Termine** (Liefertermin(e), Vertragslaufzeit, Fristen für Zahlungen/Meldungen) Optional: **Sonderbedingungen** (z. B. Rabatte, Penalties, Zahlungsmodalitäten).]]></bpmn2:documentation>
<bpmn2:incoming>sf-5</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_mCJiSA</bpmn2:incoming>
<bpmn2:outgoing>sf-8</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:task id="task_vJ0eNA" imixs:processid="2300" name="Approval by Management">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_6PFUVg"><![CDATA[Freigabe des Vertrags unter Berücksichtigung: - **Finanzielle Auswirkungen** (Budget, Liquidität, Forecast) - **Strategische Bedeutung** (Neukunde, Langfristpartner) - **Risikoanalyse** (Bonität des Partners, Marktrisiken)]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_4076SQ</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_XQfsfg" imixs:processid="2400" name="Contract Execution">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_ds3A0w"><![CDATA[**Finaler Schritt zur Vertragsaktivierung:** - **Vertragsunterzeichnung** (digital/physisch) durch beide Parteien. - **Datenaktualisierung im System**: - **Vertragspartner** → CRM/ERP (z. B. SAP, Salesforce). - **Waren/Lieferungen** → Lagerverwaltung/Logistik (z. B. Warehouse-Management-System). - **Termine** → Kalender/Projektmanagement (z. B. Microsoft Project, Jira). - **Finanzen** → Buchhaltung (Rechnungslauf, Zahlungspläne). - **Lagerort** → Bei physischen Gütern: Einlagerung und Zuordnung (z. B. per Barcode).]]></bpmn2:documentation>
</bpmn2:task>
<bpmn2:task id="task_GgAr6w" imixs:processid="2900" name="Contract Completed">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_uK2mxw"><![CDATA[**Vertragsbeendigung:** - Kündigungsfristen einhalten. - **Liquidation**: - Offene Rechnungen prüfen (Zahlungseingang/Stornierung). - Lagerbestände bereinigen (Rücklieferung/Rücknahme). - **Dokumentation**: - Grund der Kündigung festhalten (für zukünftige Entscheidungen). - Vertrag aus dem System löschen.]]></bpmn2:documentation>
<bpmn2:outgoing>sf-44</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:task id="task_0W5Llw" imixs:processid="2990" name="Request/Contract Rejected">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_XDZRNw"><![CDATA[**Abgelehter Vertrag oder Anfrage:** - Grund für die Ablehnung dokumentieren (z. B. "Partner nicht solvent"). - Feedback an Initiator geben. - END]]></bpmn2:documentation>
<bpmn2:incoming>sf-4</bpmn2:incoming>
<bpmn2:incoming>sf-9</bpmn2:incoming>
<bpmn2:incoming>sf-45</bpmn2:incoming>
</bpmn2:task>
<bpmn2:intermediateCatchEvent id="event_5P6uhg" imixs:activityid="20" name="Reject Request">
<bpmn2:documentation id="documentation_FFCYJw"/>
<bpmn2:outgoing>sf-4</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_J0JjAg" imixs:activityid="10" name="Save Draft">
<bpmn2:documentation id="documentation_2D4qfg"/>
<bpmn2:outgoing>sf-5</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_cjoSqg" imixs:activityid="20" name="Submit for Review">
<bpmn2:documentation id="documentation_44KEYA"/>
<bpmn2:incoming>sf-6</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_4076SQ</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_1FAZgA" imixs:activityid="30" name="Cancel Request">
<bpmn2:documentation id="documentation_ysbsYg"/>
<bpmn2:incoming>sequenceFlow_Jp2oQQ</bpmn2:incoming>
<bpmn2:outgoing>sf-9</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_0k30Ug" imixs:activityid="10" name="Request Adjustments">
<bpmn2:documentation id="documentation_gmDYqA"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_Xdll0Q" imixs:activityid="20" name="Final Approval">
<bpmn2:documentation id="documentation_md4VQA"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_W0tDdA" imixs:activityid="30" name="Decline Approval">
<bpmn2:documentation id="documentation_mRacqQ"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_yurw7A" imixs:activityid="10" name="Completed">
<bpmn2:documentation id="documentation_sqwDNg"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_c4BtJg" imixs:activityid="20" name="Execution Failed">
<bpmn2:documentation id="documentation_thihzw"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_zpkT5A" imixs:activityid="20" name="Correction Needed">
<bpmn2:documentation id="documentation_iUtChg"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_v7oUjw" imixs:activityid="10" name="Termination Completed">
<bpmn2:documentation id="documentation_bwy4xQ"/>
<bpmn2:incoming>sf-44</bpmn2:incoming>
<bpmn2:outgoing>sf-45</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sf-4" sourceRef="event_5P6uhg" targetRef="task_0W5Llw">
<bpmn2:documentation id="documentation_rBwcmQ"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-5" sourceRef="event_J0JjAg" targetRef="task_yrC2dw">
<bpmn2:documentation id="documentation_QaeCdA"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-6" sourceRef="gateway_SVo89A" targetRef="event_cjoSqg">
<bpmn2:documentation id="documentation_BUeEdQ"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-8" sourceRef="task_yrC2dw" targetRef="gateway_SVo89A">
<bpmn2:documentation id="documentation_Sd5bvw"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-9" sourceRef="event_1FAZgA" targetRef="task_0W5Llw">
<bpmn2:documentation id="documentation_bJindA"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-44" sourceRef="task_GgAr6w" targetRef="event_v7oUjw">
<bpmn2:documentation id="documentation_to0tvg"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sf-45" sourceRef="event_v7oUjw" targetRef="task_0W5Llw">
<bpmn2:documentation id="documentation_CjUGog"/>
</bpmn2:sequenceFlow>
<bpmn2:intermediateCatchEvent id="event_H7qtPg" imixs:activityid="20" name="Create Kundenauftrag">
<bpmn2:documentation id="documentation_w9TwIQ"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_mCJiSA" sourceRef="StartEvent_1" targetRef="task_yrC2dw">
<bpmn2:documentation id="documentation_rnZlMw"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_4076SQ" sourceRef="event_cjoSqg" targetRef="task_vJ0eNA">
<bpmn2:documentation id="documentation_2UZmwA"/>
</bpmn2:sequenceFlow>
<bpmn2:eventBasedGateway gatewayDirection="Diverging" id="gateway_SVo89A" name="">
<bpmn2:documentation id="documentation_C4eyaQ"/>
<bpmn2:incoming>sf-8</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_Jp2oQQ</bpmn2:outgoing>
<bpmn2:outgoing>sf-6</bpmn2:outgoing>
</bpmn2:eventBasedGateway>
<bpmn2:sequenceFlow id="sequenceFlow_Jp2oQQ" sourceRef="gateway_SVo89A" targetRef="event_1FAZgA">
<bpmn2:documentation id="documentation_Wzw9Yg"/>
</bpmn2:sequenceFlow>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_imRbaw"/>
<bpmn2:extensionElements>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
</bpmn2:process>
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
<bpmn2:message id="message_1" name="Message 1">
<bpmn2:documentation id="documentation_lq3hSg"/>
</bpmn2:message>
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
<dc:Bounds height="2300.0" width="4430.0" x="130.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
<dc:Bounds height="420.25001525878906" width="4400.0" x="160.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="217.0" y="177.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="189.5" y="214.10797119140625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_30">
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
<dc:Bounds height="36.0" width="36.0" x="1027.0" y="197.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="1001.138671875" y="235.10791015625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_5RftUw" id="BPMNShape_Lane_EXH7Fg">
<dc:Bounds height="651.2500152587891" width="4400.0" x="160.0" y="510.25001525878906"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_a0dlhQ" id="BPMNShape_Lane_lMjKqQ">
<dc:Bounds height="614.2500152587891" width="4400.0" x="160.0" y="1161.5000305175781"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_A6bDCA" id="BPMNShape_Lane_ErklDA">
<dc:Bounds height="614.2500152587891" width="4400.0" x="160.0" y="1775.7500457763672"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_yrC2dw" id="BPMNShape_mtNu0w">
<dc:Bounds height="50.0" width="110.0" x="340.0" y="170.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_vJ0eNA" id="BPMNShape_VSjVPA">
<dc:Bounds height="50.0" width="110.0" x="980.0" y="670.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_XQfsfg" id="BPMNShape_Vk1kAw">
<dc:Bounds height="50.0" width="110.0" x="1540.0" y="1080.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_GgAr6w" id="BPMNShape_PSzHWw">
<dc:Bounds height="50.0" width="110.0" x="2260.0" y="1300.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_0W5Llw" id="BPMNShape_WjH04g">
<dc:Bounds height="50.0" width="110.0" x="2420.0" y="400.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_5P6uhg" id="BPMNShape_1ACHNw">
<dc:Bounds height="36.0" width="36.0" x="1227.0" y="397.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_IsYLwA">
<dc:Bounds height="20.0" width="100.0" x="1195.0" y="436.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_J0JjAg" id="BPMNShape_zrh0rg">
<dc:Bounds height="36.0" width="36.0" x="377.0" y="97.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_fwqgDg">
<dc:Bounds height="20.0" width="100.0" x="345.0" y="136.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_cjoSqg" id="BPMNShape_POp4IQ">
<dc:Bounds height="36.0" width="36.0" x="827.0" y="367.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_zhSm0g">
<dc:Bounds height="20.0" width="100.0" x="795.0" y="406.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_1FAZgA" id="BPMNShape_bSO6tQ">
<dc:Bounds height="36.0" width="36.0" x="897.0" y="177.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_gAvpBQ">
<dc:Bounds height="20.0" width="100.0" x="865.0" y="216.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_0k30Ug" id="BPMNShape_Zn0P3A">
<dc:Bounds height="36.0" width="36.0" x="757.0" y="667.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_umknQA">
<dc:Bounds height="20.0" width="100.0" x="725.0" y="706.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_Xdll0Q" id="BPMNShape_Eq39Kg">
<dc:Bounds height="36.0" width="36.0" x="1317.0" y="920.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_G1WeRA">
<dc:Bounds height="20.0" width="100.0" x="1285.0" y="959.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_W0tDdA" id="BPMNShape_5yHEow">
<dc:Bounds height="36.0" width="36.0" x="1407.0" y="857.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_HkKcBw">
<dc:Bounds height="20.0" width="100.0" x="1375.0" y="896.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_yurw7A" id="BPMNShape_rWONBg">
<dc:Bounds height="36.0" width="36.0" x="1887.0" y="1147.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_s0S0ng">
<dc:Bounds height="20.0" width="100.0" x="1855.0" y="1186.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_c4BtJg" id="BPMNShape_iclF5g">
<dc:Bounds height="36.0" width="36.0" x="1857.0" y="1047.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_Gi1kIA">
<dc:Bounds height="20.0" width="100.0" x="1825.0" y="1086.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_zpkT5A" id="BPMNShape_TbcBcA">
<dc:Bounds height="36.0" width="36.0" x="1487.0" y="1317.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_9UFuzg">
<dc:Bounds height="20.0" width="100.0" x="1455.0" y="1356.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_v7oUjw" id="BPMNShape_p2C5FA">
<dc:Bounds height="36.0" width="36.0" x="2727.0" y="1357.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_DFJutA">
<dc:Bounds height="20.0" width="100.0" x="2695.0" y="1396.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_H7qtPg" id="BPMNShape_zXH5Wg">
<dc:Bounds height="36.0" width="36.0" x="1317.0" y="1087.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_BcZSCQ">
<dc:Bounds height="20.0" width="100.0" x="1285.0" y="1126.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="gateway_SVo89A" id="BPMNShape_rffh8A">
<dc:Bounds height="50.0" width="50.0" x="600.0" y="170.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_eaxusQ">
<dc:Bounds height="20.0" width="100.0" x="575.0" y="223.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sf-4" id="BPMNEdge_oO9ZTA" sourceElement="BPMNShape_1ACHNw" targetElement="BPMNShape_WjH04g">
<di:waypoint x="1263.0" y="415.0"/>
<di:waypoint x="1267.0" y="415.0"/>
<di:waypoint x="1267.0" y="425.0"/>
<di:waypoint x="2420.0" y="425.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-5" id="BPMNEdge_GZrbVw" sourceElement="BPMNShape_zrh0rg" targetElement="BPMNShape_mtNu0w">
<di:waypoint x="395.0" y="133.0"/>
<di:waypoint x="395.0" y="170.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-6" id="BPMNEdge_SKcIKQ" sourceElement="BPMNShape_rffh8A" targetElement="BPMNShape_POp4IQ">
<di:waypoint x="625.0" y="220.0"/>
<di:waypoint x="625.0" y="385.0"/>
<di:waypoint x="827.0" y="385.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-8" id="BPMNEdge_J17Pgg" sourceElement="BPMNShape_mtNu0w" targetElement="BPMNShape_rffh8A">
<di:waypoint x="450.0" y="195.0"/>
<di:waypoint x="600.0" y="195.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-9" id="BPMNEdge_oJE2uQ" sourceElement="BPMNShape_bSO6tQ" targetElement="BPMNShape_WjH04g">
<di:waypoint x="933.0" y="195.0"/>
<di:waypoint x="1677.0" y="195.0"/>
<di:waypoint x="1677.0" y="425.0"/>
<di:waypoint x="2420.0" y="425.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-44" id="BPMNEdge_IzbEkA" sourceElement="BPMNShape_PSzHWw" targetElement="BPMNShape_p2C5FA">
<di:waypoint x="2370.0" y="1329.0"/>
<di:waypoint x="3230.0" y="1329.0"/>
<di:waypoint x="3230.0" y="1375.0"/>
<di:waypoint x="2763.0" y="1375.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-45" id="BPMNEdge_TxZz3A" sourceElement="BPMNShape_p2C5FA" targetElement="BPMNShape_WjH04g">
<di:waypoint x="2763.0" y="1375.0"/>
<di:waypoint x="3282.0" y="1375.0"/>
<di:waypoint x="2474.0" y="1375.0"/>
<di:waypoint x="2474.0" y="450.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_mCJiSA" id="BPMNEdge_m1mtfw" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_mtNu0w">
<di:waypoint x="253.0" y="195.0"/>
<di:waypoint x="340.0" y="195.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_4076SQ" id="BPMNEdge_8zpyew" sourceElement="BPMNShape_POp4IQ" targetElement="BPMNShape_VSjVPA">
<di:waypoint x="863.0" y="385.0"/>
<di:waypoint x="917.0" y="385.0"/>
<di:waypoint x="917.0" y="695.0"/>
<di:waypoint x="980.0" y="695.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Jp2oQQ" id="BPMNEdge_HivQDQ" sourceElement="BPMNShape_rffh8A" targetElement="BPMNShape_bSO6tQ">
<di:waypoint x="650.0" y="195.0"/>
<di:waypoint x="897.0" y="195.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View file

@ -1,144 +0,0 @@
START
|
|- [Task: 2000] **New Contract Request**
Team: **Contract Management**
Description:
Ein neuer Vertragsanfrag wird eingereicht (z. B. durch Vertrieb oder Einkauf). Grundlegende Daten wie Vertragstyp (Kauf/Verkauf/Leasing) und Verantwortlicher müssen erfasst werden.
|-- [Event: 10] **Forward to Contract Creation** --> [Task: 2100] **Contract Creation**
|-- [Event: 20] **Reject Request** --> [Task: 2990] **Request Rejected**
|
|- [Task: 2100] **Contract Creation**
Team: **Contract Management**
Description:
Erstellung eines neuen Vertrags mit folgenden Pflichtfeldern:
- **Vertragspartner** (Name, Adresse, Kontaktdaten, Vertragsnummer)
- **Waren/Lieferungen** (Beschreibung, Menge, Einheit, Preis pro Einheit, Gesamtpreis, ggf. SKU/Artikelnummer)
- **Lagerort** (falls relevant: Lagerstandort, Lagerverantwortlicher)
- **Termine** (Liefertermin(e), Vertragslaufzeit, Fristen für Zahlungen/Meldungen)
Optional: **Sonderbedingungen** (z. B. Rabatte, Penalties, Zahlungsmodalitäten).
|-- [Event: 10] **Save Draft** --> [Task: 2100] **Contract Creation** *(Iteration für Korrekturen)*
|-- [Event: 20] **Submit for Review** --> [Task: 2200] **Legal Review**
|-- [Event: 30] **Cancel Request** --> [Task: 2990] **Request Rejected**
|
|- [Task: 2200] **Legal Review**
Team: **Legal/Compliance**
Description:
Prüfung auf rechtliche Korrektheit und Vollständigkeit:
- Vertragsklauseln (AGB, Gewährleistungen, Haftung)
- Compliance mit internen Richtlinien (z. B. Risikobewertung bei neuen Partnern)
- Terminpläne (z. B. Prüfung von Fristen)
|-- [Event: 10] **Request Changes** --> [Task: 2100] **Contract Creation** *(Rückgabe zur Korrektur)*
|-- [Event: 20] **Approve Contract** --> [Task: 2300] **Approval by Management**
|-- [Event: 30] **Reject Contract** --> [Task: 2990] **Contract Rejected**
|
|- [Task: 2300] **Approval by Management**
Team: **Senior Management/Finance**
Description:
Freigabe des Vertrags unter Berücksichtigung:
- **Finanzielle Auswirkungen** (Budget, Liquidität, Forecast)
- **Strategische Bedeutung** (Neukunde, Langfristpartner)
- **Risikoanalyse** (Bonität des Partners, Marktrisiken)
|-- [Event: 10] **Request Adjustments** --> [Task: 2100] **Contract Creation** *(z. B. Preisanpassung)*
|-- [Event: 20] **Final Approval** --> [Task: 2400] **Contract Execution**
|-- [Event: 30] **Decline Approval** --> [Task: 2990] **Contract Rejected**
|
|- [Task: 2400] **Contract Execution**
Team: **Contract Management / Operations**
Description:
**Finaler Schritt zur Vertragsaktivierung:**
- **Vertragsunterzeichnung** (digital/physisch) durch beide Parteien.
- **Datenaktualisierung im System**:
- **Vertragspartner** → CRM/ERP (z. B. SAP, Salesforce).
- **Waren/Lieferungen** → Lagerverwaltung/Logistik (z. B. Warehouse-Management-System).
- **Termine** → Kalender/Projektmanagement (z. B. Microsoft Project, Jira).
- **Finanzen** → Buchhaltung (Rechnungslauf, Zahlungspläne).
- **Lagerort** → Bei physischen Gütern: Einlagerung und Zuordnung (z. B. per Barcode).
|-- [Event: 10] **Contract Signed** --> [Task: 2500] **Post-Contract Setup**
|-- [Event: 20] **Execution Failed** --> [Task: 2990] **Contract Rejected** *(z. B. Unterzeichnung gescheitert)*
|
|- [Task: 2500] **Post-Contract Setup**
Team: **Cross-Functional (Logistik, Sales, Finance)**
Description:
**Nachbereitung nach Vertragsunterzeichnung:**
- **Logistik**:
- Lagerbestände anpassen (bei Lieferverträgen).
- Lieferpläne erstellen (Termine, Routen, Verantwortliche).
- **Vertrieb**:
- Kundenkommunikation (Bestätigungsmail, nächste Schritte).
- **Finanzen**:
- Zahlungsbedingungen konfigurieren (z. B. Skonto, Raten).
- Budgetreservierungen freigeben.
- **Monitoring**:
- **KPIs** festlegen (z. B. Liefertreue, Zahlungseingänge).
- **Audit-Trail** für Nachverfolgung.
|-- [Event: 10] **Setup Completed** --> [Task: 2600] **Contract Active**
|-- [Event: 20] **Correction Needed** --> [Task: 2400] **Contract Execution** *(z. B. Lagerfehler korrigieren)*
|
|- [Task: 2600] **Contract Active**
Team: **Contract Owner (z. B. Account Manager)**
Description:
**Laufender Vertrag:**
- **Regelmäßige Überprüfungen**:
- Terminpläne (Lieferungen, Zahlungen, Kündigungsfristen).
- Performance des Partners (z. B. Lieferzuverlässigkeit).
- **Änderungsmanagement**:
- Anpassungen (z. B. Mengenänderungen, Preisanpassungen) müssen neu freigegeben werden (→ Rückkehr zu [Task: 2100]).
|-- [Event: 10] **Renewal Due** --> [Task: 2700] **Contract Renewal**
|-- [Event: 20] **Termination Requested** --> [Task: 2900] **Contract Termination**
|-- [Event: 30] **Escalation** --> [Task: 2800] **Contract Dispute**
|
|- [Task: 2700] **Contract Renewal**
Team: **Contract Management / Sales**
Description:
**Vertragsverlängerung/Anpassung:**
- Analyse der Vertragsperformance (z. B. Umsatz, Partnerzufriedenheit).
- Angebot für Verlängerung oder neue Bedingungen erstellen.
- Prozess wie [Task: 2100] **Contract Creation** wiederholen.
|-- [Event: 10] **Renewal Approved** --> [Task: 2600] **Contract Active**
|-- [Event: 20] **Renewal Rejected** --> [Task: 2900] **Contract Termination**
|
|- [Task: 2800] **Contract Dispute**
Team: **Legal / Dispute Resolution**
Description:
**Konfliktmanagement:**
- Ursache analysieren (z. B. nicht erfüllte Liefertermine, Preisstreitigkeiten).
- Mediation oder rechtliche Schritte einleiten.
- Bei Einigung: Anpassung des Vertrags ([Task: 2100]).
- Bei Scheitern: [Task: 2900] **Contract Termination**.
|-- [Event: 10] **Dispute Resolved** --> [Task: 2600] **Contract Active**
|-- [Event: 20] **Termination Due to Dispute** --> [Task: 2900] **Contract Termination**
|
|- [Task: 2900] **Contract Termination**
Team: **Contract Management / Legal**
Description:
**Vertragsbeendigung:**
- Kündigungsfristen einhalten.
- **Liquidation**:
- Offene Rechnungen prüfen (Zahlungseingang/Stornierung).
- Lagerbestände bereinigen (Rücklieferung/Rücknahme).
- **Dokumentation**:
- Grund der Kündigung festhalten (für zukünftige Entscheidungen).
- Vertrag aus dem System löschen.
|-- [Event: 10] **Termination Completed** --> [Task: 2990] **Process Ended**
|
|- [Task: 2990] **Request/Contract Rejected**
Team: **Contract Management**
Description:
**Abgelehter Vertrag oder Anfrage:**
- Grund für die Ablehnung dokumentieren (z. B. "Partner nicht solvent").
- Feedback an Initiator geben.
|-- [Event: 10] **Close Case** --> END
|
|- END
Description: **Workflow abgeschlossen** (Vertrag aktiv, beendet oder abgelehnt).

View file

@ -1,820 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowmodelversion" type="xs:string">
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
</imixs:item>
<imixs:item name="txtfieldmapping" type="xs:string">
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
</imixs:item>
<imixs:item name="txttimefieldmapping" type="xs:string">
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
</imixs:item>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
<bpmn2:documentation id="documentation_3xKpCQ"/>
</bpmn2:participant>
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
</bpmn2:collaboration>
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane_1" name="Team">
<bpmn2:documentation id="documentation_gvQWYQ"/>
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_DG70UA" name="Sales Operations">
<bpmn2:flowNodeRef>task_X3JEMQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_DsQHAA</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_UdE1FQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_RDx0tQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_hNqu8Q</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_0Uti6Q</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_00ytag" name="Finance / Legal">
<bpmn2:flowNodeRef>task_0qFkuw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_LsGwGw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_VDjbDQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_YIeVQg</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_4fHTYA" name="Pre-Sales / Engineers">
<bpmn2:flowNodeRef>task_q3AJTA</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_w7iCNQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_tPPF0w</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_aGk1Mw" name="Purchasing / Procurement">
<bpmn2:flowNodeRef>task_U17j4w</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_79P3wA" name="Logistics / Technical Support">
<bpmn2:flowNodeRef>task_dkvx9A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_u6xa6w</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_zdkmmA" name="Finance">
<bpmn2:flowNodeRef>task_T7gMeg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_rukJhQ</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="StartEvent_1" name="Start">
<bpmn2:documentation id="documentation_IUTaAQ"/>
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="Documentation_2"/>
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:endEvent id="EndEvent_2" name="End">
<bpmn2:documentation id="documentation_mHDfBQ"/>
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
<bpmn2:documentation id="documentation_RKidfg"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
<bpmn2:documentation id="documentation_V7pFuw"/>
</bpmn2:sequenceFlow>
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
<bpmn2:documentation id="documentation_e2Geig"/>
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
<bpmn2:documentation id="documentation_d1EdlQ"/>
</bpmn2:sequenceFlow>
<bpmn2:task id="task_X3JEMQ" imixs:processid="2000" name="Order Received">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_sesL1g"><![CDATA[A new purchase order from a Reseller has been received via EDI, Email or Portal. Initial check for completeness of SKU and quantities.]]></bpmn2:documentation>
<bpmn2:outgoing>sf-1</bpmn2:outgoing>
<bpmn2:incoming>sf-3</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_0qFkuw" imixs:processid="2100" name="Credit &amp; Compliance Check">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_HNaSKw"><![CDATA[Verification of the Reseller's credit limit and export control compliance (especially for US-based cybersecurity vendors).]]></bpmn2:documentation>
<bpmn2:incoming>sf-2</bpmn2:incoming>
<bpmn2:outgoing>sf-4</bpmn2:outgoing>
<bpmn2:incoming>sf-6</bpmn2:incoming>
<bpmn2:outgoing>sf-7</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:task id="task_q3AJTA" imixs:processid="2200" name="Technical Validation">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_eH1H6Q"><![CDATA[VAD Service: Review if the ordered configuration/solution is technically sound and compatible (e.g., bundles, maintenance periods).]]></bpmn2:documentation>
<bpmn2:incoming>sf-5</bpmn2:incoming>
<bpmn2:outgoing>sf-9</bpmn2:outgoing>
<bpmn2:incoming>sf-11</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_U17j4w" imixs:processid="2300" name="Vendor Ordering">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_5oT1YQ"><![CDATA[Order is placed at the Vendor (e.g., Fortinet, Check Point). Waiting for Vendor confirmation and license/hardware allocation. |-- [Event: 10] Confirmed by Vendor --> [Task: 2400] Delivery & Provisioning |-- [Event: 20] Delay Notification --> [Task: 2300] Vendor Ordering]]></bpmn2:documentation>
<bpmn2:incoming>sf-10</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_dkvx9A" imixs:processid="2400" name="Delivery &amp; Provisioning">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_aNWqug"><![CDATA[Physical shipment of hardware or digital provisioning of license keys/cloud access to the Reseller.]]></bpmn2:documentation>
<bpmn2:outgoing>sf-12</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:task id="task_T7gMeg" imixs:processid="2500" name="Invoicing">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_ggUUuQ"><![CDATA[Final invoice is generated and sent to the Reseller. Update of ERP system records. |-- [Event: 10] Invoice Sent --> [Task: 2800] Completed]]></bpmn2:documentation>
<bpmn2:incoming>sf-13</bpmn2:incoming>
<bpmn2:incoming>sf-14</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_DsQHAA" imixs:processid="2800" name="Completed">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_2wE86A"><![CDATA[Order successfully fulfilled and invoiced. |-- [Event: 10] Archive Order --> [Task: 2800] Completed]]></bpmn2:documentation>
</bpmn2:task>
<bpmn2:task id="task_UdE1FQ" imixs:processid="2900" name="Cancelled">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_aXvupw"><![CDATA[The order was cancelled due to commercial, technical, or compliance reasons. |-- [Event: 10] Inform Vendor & Reseller --> [Task: 2800] Completed |-- [Event: 30] Delete Record --> [Task: 2990] Deleted END]]></bpmn2:documentation>
<bpmn2:incoming>sf-8</bpmn2:incoming>
</bpmn2:task>
<bpmn2:task id="task_RDx0tQ" imixs:processid="2990" name="Deleted">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_WSBv0w"/>
</bpmn2:task>
<bpmn2:intermediateCatchEvent id="event_hNqu8Q" imixs:activityid="10" name="Validated">
<bpmn2:documentation id="documentation_HpkRIg"/>
<bpmn2:incoming>sf-1</bpmn2:incoming>
<bpmn2:outgoing>sf-2</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_0Uti6Q" imixs:activityid="20" name="Data Missing">
<bpmn2:documentation id="documentation_jke3RA"/>
<bpmn2:outgoing>sf-3</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_LsGwGw" imixs:activityid="10" name="Approved">
<bpmn2:documentation id="documentation_1Z7lLQ"/>
<bpmn2:incoming>sf-4</bpmn2:incoming>
<bpmn2:outgoing>sf-5</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_VDjbDQ" imixs:activityid="20" name="Hold">
<bpmn2:documentation id="documentation_c39vVA"/>
<bpmn2:outgoing>sf-6</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_YIeVQg" imixs:activityid="30" name="Rejected">
<bpmn2:documentation id="documentation_ezlA2Q"/>
<bpmn2:incoming>sf-7</bpmn2:incoming>
<bpmn2:outgoing>sf-8</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_w7iCNQ" imixs:activityid="10" name="Technical Clear">
<bpmn2:documentation id="documentation_L830uw"/>
<bpmn2:incoming>sf-9</bpmn2:incoming>
<bpmn2:outgoing>sf-10</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_tPPF0w" imixs:activityid="20" name="Adjustment Needed">
<bpmn2:documentation id="documentation_yfTMmg"/>
<bpmn2:outgoing>sf-11</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_u6xa6w" imixs:activityid="10" name="Fulfilled">
<bpmn2:documentation id="documentation_ffDPSg"/>
<bpmn2:incoming>sf-12</bpmn2:incoming>
<bpmn2:outgoing>sf-13</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:intermediateCatchEvent id="event_rukJhQ" imixs:activityid="10" name="Dispute">
<bpmn2:documentation id="documentation_J0NUmg"/>
<bpmn2:outgoing>sf-14</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sf-1" sourceRef="task_X3JEMQ" targetRef="event_hNqu8Q"/>
<bpmn2:sequenceFlow id="sf-2" sourceRef="event_hNqu8Q" targetRef="task_0qFkuw"/>
<bpmn2:sequenceFlow id="sf-3" sourceRef="event_0Uti6Q" targetRef="task_X3JEMQ"/>
<bpmn2:sequenceFlow id="sf-4" sourceRef="task_0qFkuw" targetRef="event_LsGwGw"/>
<bpmn2:sequenceFlow id="sf-5" sourceRef="event_LsGwGw" targetRef="task_q3AJTA"/>
<bpmn2:sequenceFlow id="sf-6" sourceRef="event_VDjbDQ" targetRef="task_0qFkuw"/>
<bpmn2:sequenceFlow id="sf-7" sourceRef="task_0qFkuw" targetRef="event_YIeVQg"/>
<bpmn2:sequenceFlow id="sf-8" sourceRef="event_YIeVQg" targetRef="task_UdE1FQ"/>
<bpmn2:sequenceFlow id="sf-9" sourceRef="task_q3AJTA" targetRef="event_w7iCNQ"/>
<bpmn2:sequenceFlow id="sf-10" sourceRef="event_w7iCNQ" targetRef="task_U17j4w"/>
<bpmn2:sequenceFlow id="sf-11" sourceRef="event_tPPF0w" targetRef="task_q3AJTA"/>
<bpmn2:sequenceFlow id="sf-12" sourceRef="task_dkvx9A" targetRef="event_u6xa6w"/>
<bpmn2:sequenceFlow id="sf-13" sourceRef="event_u6xa6w" targetRef="task_T7gMeg"/>
<bpmn2:sequenceFlow id="sf-14" sourceRef="event_rukJhQ" targetRef="task_T7gMeg"/>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_imRbaw"/>
<bpmn2:extensionElements>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
</bpmn2:process>
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
<bpmn2:message id="message_1" name="Message 1">
<bpmn2:documentation id="documentation_lq3hSg"/>
</bpmn2:message>
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
<dc:Bounds height="1610.0" width="4430.0" x="130.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_30">
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
<di:waypoint x="273.0" y="155.0"/>
<di:waypoint x="367.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
<di:waypoint x="600.0" y="155.0"/>
<di:waypoint x="697.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
<di:waypoint x="403.0" y="155.0"/>
<di:waypoint x="490.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="lane_DG70UA" id="BPMNShape_Lane_jFYG6Q">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="320.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_00ytag" id="BPMNShape_Lane_xhK1gw">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="550.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_4fHTYA" id="BPMNShape_Lane_6GK7cA">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="780.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_aGk1Mw" id="BPMNShape_Lane_tjmgKA">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1010.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_79P3wA" id="BPMNShape_Lane_pPNT5g">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1240.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_zdkmmA" id="BPMNShape_Lane_FtseBQ">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1470.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_X3JEMQ" id="BPMNShape_jq7RHA">
<dc:Bounds height="50.0" width="110.0" x="300.0" y="390.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_0qFkuw" id="BPMNShape_3K2f0Q">
<dc:Bounds height="50.0" width="110.0" x="610.0" y="620.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_q3AJTA" id="BPMNShape_sUEenw">
<dc:Bounds height="50.0" width="110.0" x="920.0" y="850.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_U17j4w" id="BPMNShape_W8fe4Q">
<dc:Bounds height="50.0" width="110.0" x="1230.0" y="1080.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_dkvx9A" id="BPMNShape_ubdkUw">
<dc:Bounds height="50.0" width="110.0" x="1540.0" y="1310.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_T7gMeg" id="BPMNShape_hIOUAw">
<dc:Bounds height="50.0" width="110.0" x="1850.0" y="1540.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_DsQHAA" id="BPMNShape_Vn2fuQ">
<dc:Bounds height="50.0" width="110.0" x="2160.0" y="390.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_UdE1FQ" id="BPMNShape_QQ4bfw">
<dc:Bounds height="50.0" width="110.0" x="2470.0" y="390.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_RDx0tQ" id="BPMNShape_3XWFIw">
<dc:Bounds height="50.0" width="110.0" x="2780.0" y="390.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_hNqu8Q" id="BPMNShape_KOADdw">
<dc:Bounds height="36.0" width="36.0" x="337.0" y="460.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_BF0Ebw">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_0Uti6Q" id="BPMNShape_DcRdSQ">
<dc:Bounds height="36.0" width="36.0" x="387.0" y="460.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_t2gQcA">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_LsGwGw" id="BPMNShape_UiA5Yg">
<dc:Bounds height="36.0" width="36.0" x="647.0" y="690.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_ryMLDA">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_VDjbDQ" id="BPMNShape_xBD1vQ">
<dc:Bounds height="36.0" width="36.0" x="697.0" y="690.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_BSXHzQ">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_YIeVQg" id="BPMNShape_BgjXgw">
<dc:Bounds height="36.0" width="36.0" x="747.0" y="690.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_v8qOow">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_w7iCNQ" id="BPMNShape_qw6I8A">
<dc:Bounds height="36.0" width="36.0" x="957.0" y="920.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_y0gzLg">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_tPPF0w" id="BPMNShape_e93ltA">
<dc:Bounds height="36.0" width="36.0" x="1007.0" y="920.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_7bv15g">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_u6xa6w" id="BPMNShape_Zgddmw">
<dc:Bounds height="36.0" width="36.0" x="1577.0" y="1380.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_jnAdow">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_rukJhQ" id="BPMNShape_GQobtA">
<dc:Bounds height="36.0" width="36.0" x="1887.0" y="1610.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_BqocNw">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sf-1" id="BPMNEdge_6SOP2w" sourceElement="BPMNShape_jq7RHA" targetElement="BPMNShape_KOADdw">
<di:waypoint x="355.0" y="415.0"/>
<di:waypoint x="355.0" y="478.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-2" id="BPMNEdge_LM1Ncg" sourceElement="BPMNShape_KOADdw" targetElement="BPMNShape_3K2f0Q">
<di:waypoint x="355.0" y="478.0"/>
<di:waypoint x="665.0" y="645.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-3" id="BPMNEdge_JI0a9g" sourceElement="BPMNShape_DcRdSQ" targetElement="BPMNShape_jq7RHA">
<di:waypoint x="405.0" y="478.0"/>
<di:waypoint x="355.0" y="415.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-4" id="BPMNEdge_qQOQfA" sourceElement="BPMNShape_3K2f0Q" targetElement="BPMNShape_UiA5Yg">
<di:waypoint x="665.0" y="645.0"/>
<di:waypoint x="665.0" y="708.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-5" id="BPMNEdge_L6cT5A" sourceElement="BPMNShape_UiA5Yg" targetElement="BPMNShape_sUEenw">
<di:waypoint x="665.0" y="708.0"/>
<di:waypoint x="975.0" y="875.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-6" id="BPMNEdge_pTz0gg" sourceElement="BPMNShape_xBD1vQ" targetElement="BPMNShape_3K2f0Q">
<di:waypoint x="715.0" y="708.0"/>
<di:waypoint x="665.0" y="645.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-7" id="BPMNEdge_fcnNzw" sourceElement="BPMNShape_3K2f0Q" targetElement="BPMNShape_BgjXgw">
<di:waypoint x="665.0" y="645.0"/>
<di:waypoint x="765.0" y="708.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-8" id="BPMNEdge_oL0lZw" sourceElement="BPMNShape_BgjXgw" targetElement="BPMNShape_QQ4bfw">
<di:waypoint x="765.0" y="708.0"/>
<di:waypoint x="2525.0" y="415.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-9" id="BPMNEdge_y0BJxQ" sourceElement="BPMNShape_sUEenw" targetElement="BPMNShape_qw6I8A">
<di:waypoint x="975.0" y="875.0"/>
<di:waypoint x="975.0" y="938.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-10" id="BPMNEdge_e6L0iA" sourceElement="BPMNShape_qw6I8A" targetElement="BPMNShape_W8fe4Q">
<di:waypoint x="975.0" y="938.0"/>
<di:waypoint x="1285.0" y="1105.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-11" id="BPMNEdge_s8Telw" sourceElement="BPMNShape_e93ltA" targetElement="BPMNShape_sUEenw">
<di:waypoint x="1025.0" y="938.0"/>
<di:waypoint x="975.0" y="875.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-12" id="BPMNEdge_7D51VA" sourceElement="BPMNShape_ubdkUw" targetElement="BPMNShape_Zgddmw">
<di:waypoint x="1595.0" y="1335.0"/>
<di:waypoint x="1595.0" y="1398.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-13" id="BPMNEdge_kX1vjg" sourceElement="BPMNShape_Zgddmw" targetElement="BPMNShape_hIOUAw">
<di:waypoint x="1595.0" y="1398.0"/>
<di:waypoint x="1905.0" y="1565.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sf-14" id="BPMNEdge_lDS21g" sourceElement="BPMNShape_GQobtA" targetElement="BPMNShape_hIOUAw">
<di:waypoint x="1905.0" y="1628.0"/>
<di:waypoint x="1905.0" y="1565.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View file

@ -1,64 +0,0 @@
Ordermanagement
START
|
|- [Task: 2000] Order Received
| Team: Sales Operations
| Description:
| A new purchase order from a Reseller has been received via EDI, Email or Portal. Initial check for completeness of SKU and quantities.
| |-- [Event: 10] Validated (Order complete) --> [Task: 2100] Credit & Compliance Check
| |-- [Event: 20] Data Missing (Contact Reseller) --> [Task: 2000] Order Received
| |-- [Event: 30] Cancel Order --> [Task: 2900] Cancelled
|
|- [Task: 2100] Credit & Compliance Check
| Team: Finance / Legal
| Description:
| Verification of the Reseller's credit limit and export control compliance (especially for US-based cybersecurity vendors).
| |-- [Event: 10] Approved (Credit and Compliance OK) --> [Task: 2200] Technical Validation
| |-- [Event: 20] Hold (Credit limit exceeded) --> [Task: 2100] Credit & Compliance Check
| |-- [Event: 30] Rejected (Compliance risk) --> [Task: 2900] Cancelled
|
|- [Task: 2200] Technical Validation
| Team: Pre-Sales / Engineers
| Description:
| VAD Service: Review if the ordered configuration/solution is technically sound and compatible (e.g., bundles, maintenance periods).
| |-- [Event: 10] Technical Clear (Configuration valid) --> [Task: 2300] Vendor Ordering
| |-- [Event: 20] Adjustment Needed (Consult with Reseller) --> [Task: 2200] Technical Validation
| |-- [Event: 30] Reject Design --> [Task: 2900] Cancelled
|
|- [Task: 2300] Vendor Ordering
| Team: Purchasing / Procurement
| Description:
| Order is placed at the Vendor (e.g., Fortinet, Check Point). Waiting for Vendor confirmation and license/hardware allocation.
| |-- [Event: 10] Confirmed by Vendor --> [Task: 2400] Delivery & Provisioning
| |-- [Event: 20] Delay Notification --> [Task: 2300] Vendor Ordering
|
|- [Task: 2400] Delivery & Provisioning
| Team: Logistics / Technical Support
| Description:
| Physical shipment of hardware or digital provisioning of license keys/cloud access to the Reseller.
| |-- [Event: 10] Fulfilled (Delivery/Provisioning completed) --> [Task: 2500] Invoicing
| |-- [Event: 11] Partial Delivery --> [Task: 2400] Delivery & Provisioning
|
|- [Task: 2500] Invoicing
| Team: Finance
| Description:
| Final invoice is generated and sent to the Reseller. Update of ERP system records.
| |-- [Event: 10] Invoice Sent --> [Task: 2800] Completed
| |-- [Event: 20] Dispute (Correction required) --> [Task: 2500] Invoicing
|
|- [Task: 2800] Completed
| Team: Sales Operations
| Description:
| Order successfully fulfilled and invoiced.
| |-- [Event: 10] Archive Order --> [Task: 2800] Completed
|
|- [Task: 2900] Cancelled
| Team: Sales Operations
| Description:
| The order was cancelled due to commercial, technical, or compliance reasons.
| |-- [Event: 10] Inform Vendor & Reseller --> [Task: 2800] Completed
| |-- [Event: 30] Delete Record --> [Task: 2990] Deleted
|
END

View file

@ -1,78 +0,0 @@
Business Process: Risk Management
START
|
|- [Task: 1000] Risk Identification
| Team: Risk Owner (Operational Unit)
| Description:
| A potential risk has been identified within an operational unit. The Risk Owner captures basic data (Category, Description, Early Warning Indicators) to initiate the process in accordance with KonTraG.
| |-- [Event: 10] Submit Proposal (Forward to Central Risk Management) --> [Task: 1100] Validation
| |-- [Event: 20] Discard (Draft deleted) --> [Task: 1990] Deleted
|
|- [Task: 1100] Validation
| Team: Central Risk Management
| Description:
| Central function checks if the identified issued qualifies as a relevant risk or if it is a duplicate.
| |-- [Event: 10] Confirm Risk (Risk is valid, proceed to assessment) --> [Task: 1200] Gross Assessment
| |-- [Event: 20] Reject (Not a risk or duplicate) --> [Task: 1900] Archived
| |-- [Event: 30] Request Info (Send back to Owner for details) --> [Task: 1000] Risk Identification
|
|- [Task: 1200] Gross Assessment
| Team: Risk Owner (Operational Unit)
| Description:
| Quantitative assessment of the risk WITHOUT considering planned or existing measures. Impact and Probability are estimated to determine the Gross Risk Score.
| |-- [Event: 10] Save Gross Data (Proceed to Measure Definition) --> [Task: 1300] Measure Definition
|
|- [Task: 1300] Measure Definition
| Team: Risk Owner (Operational Unit)
| Description:
| Definition of risk mitigating measures (Avoid, Reduce, Transfer, Accept). Documentation of costs and responsibilities for these measures.
| |-- [Event: 10] Measures Defined (Proceed to Net Assessment) --> [Task: 1400] Net Assessment
| |-- [Event: 20] Update Assessment (Go back to Gross Assessment) --> [Task: 1200] Gross Assessment
|
|- [Task: 1400] Net Assessment
| Team: Risk Owner (Operational Unit)
| Description:
| Re-evaluation of Impact and Probability taking the defined measures into account (Residual Risk). Crucial for IDW PS 340 compliance.
| |-- [Event: 10] Submit for Aggregation (Forward to Central RM) --> [Task: 1500] Aggregation & Analysis
|
|- [Task: 1500] Aggregation & Analysis
| Team: Central Risk Management
| Description:
| The risk is analyzed in the context of the total risk portfolio (Risk Aggregation/Monte Carlo Simulation) to check against the company's Risk Bearing Capacity.
| |-- [Event: 10] Approve (Risk within appetite, standard monitoring) --> [Task: 1600] Monitoring
| |-- [Event: 20] Insufficient Mitigation (Measures not enough, send back) --> [Task: 1300] Measure Definition
| |-- [Event: 30] Critical Escalation (Threat to existence, forward to Board) --> [Task: 1550] Board Review
|
|- [Task: 1550] Board Review
| Team: Management Board / Risk Committee
| Description:
| High-level decision required. Risk exceeds risk bearing capacity or is a "bestandsgefährdendes Risiko" (§91 Abs. 2 AktG).
| |-- [Event: 10] Accept Risk (Special approval granted) --> [Task: 1600] Monitoring
| |-- [Event: 20] Demand Action (Force new measures) --> [Task: 1300] Measure Definition
|
|- [Task: 1600] Monitoring
| Team: Risk Owner (Operational Unit)
| Description:
| Continuous surveillance of the risk and the effectiveness of measures. Periodic review (e.g., quarterly).
| |-- [Event: 10] Report: No Change (Keep monitoring) --> [Task: 1600] Monitoring
| |-- [Event: 20] Risk Changed (Values or measures changed) --> [Task: 1200] Gross Assessment
| |-- [Event: 30] Risk Obsolete (Risk no longer exists) --> [Task: 1800] Closure Review
|
|- [Task: 1800] Closure Review
| Team: Central Risk Management
| Description:
| Final check if the risk can really be closed.
| |-- [Event: 10] Close Risk (Archive) --> [Task: 1900] Archived
| |-- [Event: 20] Deny Closure (Keep active) --> [Task: 1600] Monitoring
|
|- [Task: 1900] Archived
| Team: System
| Description:
| Risk is closed but kept for audit trails and historical data analysis.
| |-- [Event: 10] Reactivate --> [Task: 1100] Validation
|
END
|
|- [Task: 1990] Deleted
|

View file

@ -1,319 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowmodelversion" type="xs:string">
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
</imixs:item>
<imixs:item name="txtfieldmapping" type="xs:string">
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
</imixs:item>
<imixs:item name="txttimefieldmapping" type="xs:string">
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
</imixs:item>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
<bpmn2:documentation id="documentation_3xKpCQ"/>
</bpmn2:participant>
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
</bpmn2:collaboration>
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane_1" name="Team">
<bpmn2:documentation id="documentation_gvQWYQ"/>
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_HQd8AQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_6HJvNQ</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_HQ9VcQ</bpmn2:flowNodeRef>
</bpmn2:lane>
<bpmn2:lane id="lane_EQOgOg" name="Accounting"/>
<bpmn2:lane id="lane_2tdU0Q" name="Sales Team"/>
</bpmn2:laneSet>
<bpmn2:startEvent id="StartEvent_1" name="Start">
<bpmn2:documentation id="documentation_IUTaAQ"/>
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="Documentation_2"/>
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:endEvent id="EndEvent_2" name="End">
<bpmn2:documentation id="documentation_mHDfBQ"/>
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
<bpmn2:documentation id="documentation_RKidfg"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
<bpmn2:documentation id="documentation_V7pFuw"/>
</bpmn2:sequenceFlow>
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
<bpmn2:documentation id="documentation_e2Geig"/>
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
<bpmn2:documentation id="documentation_d1EdlQ"/>
</bpmn2:sequenceFlow>
<bpmn2:task id="task_HQd8AQ" imixs:processid="1000" name="Task-2">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_z6PPww"/>
<bpmn2:outgoing>sequence-flow-1</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:intermediateCatchEvent id="event_6HJvNQ" imixs:activityid="10" name="Event-1">
<bpmn2:documentation id="documentation_PoRwdg"/>
<bpmn2:incoming>sequence-flow-1</bpmn2:incoming>
<bpmn2:outgoing>sequence-flow-2</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:task id="task_HQ9VcQ" imixs:processid="1100" name="Import">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_CdXjvg"/>
<bpmn2:incoming>sequence-flow-2</bpmn2:incoming>
</bpmn2:task>
<bpmn2:sequenceFlow id="sequence-flow-1" sourceRef="task_HQd8AQ" targetRef="event_6HJvNQ"/>
<bpmn2:sequenceFlow id="sequence-flow-2" sourceRef="event_6HJvNQ" targetRef="task_HQ9VcQ"/>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_imRbaw"/>
<bpmn2:extensionElements>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
</bpmn2:process>
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
<bpmn2:message id="message_1" name="Message 1">
<bpmn2:documentation id="documentation_lq3hSg"/>
</bpmn2:message>
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
<dc:Bounds height="690.0" width="4430.0" x="130.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_30">
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
<di:waypoint x="273.0" y="155.0"/>
<di:waypoint x="367.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
<di:waypoint x="600.0" y="155.0"/>
<di:waypoint x="697.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
<di:waypoint x="403.0" y="155.0"/>
<di:waypoint x="490.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="lane_EQOgOg" id="BPMNShape_Lane_vbFCIg">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="320.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="lane_2tdU0Q" id="BPMNShape_Lane_AJQqiw">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="550.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_HQd8AQ" id="BPMNShape_SWNkXw">
<dc:Bounds height="50.0" width="110.0" x="150.0" y="200.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_6HJvNQ" id="BPMNShape_GCOCOA">
<dc:Bounds height="36.0" width="36.0" x="350.0" y="200.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_K3GzxA">
<dc:Bounds x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_HQ9VcQ" id="BPMNShape_0vb1vw">
<dc:Bounds height="50.0" width="110.0" x="450.0" y="200.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequence-flow-1" id="BPMNEdge_nhNbcg" sourceElement="BPMNShape_SWNkXw" targetElement="BPMNShape_GCOCOA">
<di:waypoint x="205.0" y="225.0"/>
<di:waypoint x="368.0" y="218.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequence-flow-2" id="BPMNEdge_NLlZ5g" sourceElement="BPMNShape_GCOCOA" targetElement="BPMNShape_0vb1vw">
<di:waypoint x="368.0" y="218.0"/>
<di:waypoint x="505.0" y="225.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View file

@ -1,77 +0,0 @@
Business Process: Risk Management Cycle (IDW PS 340)
START
|
|- [Task: 1000] Risk Identification
| Team: Risk Owner (Operational Unit)
| Description:
| A potential risk has been identified within an operational unit. The Risk Owner captures basic data (Category, Description, Early Warning Indicators) to initiate the process in accordance with KonTraG.
| |-- [Event: 10] Submit Proposal (Forward to Central Risk Management) --> [Task: 1100] Validation
| |-- [Event: 20] Discard (Draft deleted) --> [Task: 1990] Deleted
|
|- [Task: 1100] Validation
| Team: Central Risk Management
| Description:
| Central function checks if the identified issue qualifies as a relevant risk or if it is a duplicate.
| |-- [Event: 10] Confirm Risk (Risk is valid, proceed to assessment) --> [Task: 1200] Gross Assessment
| |-- [Event: 20] Reject (Not a risk or duplicate) --> [Task: 1900] Archived
| |-- [Event: 30] Request Info (Send back to Owner for details) --> [Task: 1000] Risk Identification
|
|- [Task: 1200] Gross Assessment
| Team: Risk Owner (Operational Unit)
| Description:
| Quantitative assessment of the risk WITHOUT considering planned or existing measures. Impact and Probability are estimated to determine the Gross Risk Score.
| |-- [Event: 10] Save Gross Data (Proceed to Measure Definition) --> [Task: 1300] Measure Definition
|
|- [Task: 1300] Measure Definition
| Team: Risk Owner (Operational Unit)
| Description:
| Definition of risk mitigating measures (Avoid, Reduce, Transfer, Accept). Documentation of costs and responsibilities for these measures.
| |-- [Event: 10] Measures Defined (Proceed to Net Assessment) --> [Task: 1400] Net Assessment
| |-- [Event: 20] Update Assessment (Go back to Gross Assessment) --> [Task: 1200] Gross Assessment
|
|- [Task: 1400] Net Assessment
| Team: Risk Owner (Operational Unit)
| Description:
| Re-evaluation of Impact and Probability taking the defined measures into account (Residual Risk). Crucial for IDW PS 340 compliance.
| |-- [Event: 10] Submit for Aggregation (Forward to Central RM) --> [Task: 1500] Aggregation & Analysis
|
|- [Task: 1500] Aggregation & Analysis
| Team: Central Risk Management
| Description:
| The risk is analyzed in the context of the total risk portfolio (Risk Aggregation/Monte Carlo Simulation) to check against the company's Risk Bearing Capacity.
| |-- [Event: 10] Approve (Risk within appetite, standard monitoring) --> [Task: 1600] Monitoring
| |-- [Event: 20] Insufficient Mitigation (Measures not enough, send back) --> [Task: 1300] Measure Definition
| |-- [Event: 30] Critical Escalation (Threat to existence, forward to Board) --> [Task: 1550] Board Review
|
|- [Task: 1550] Board Review
| Team: Management Board / Risk Committee
| Description:
| High-level decision required. Risk exceeds risk bearing capacity or is a "bestandsgefährdendes Risiko" (§91 Abs. 2 AktG).
| |-- [Event: 10] Accept Risk (Special approval granted) --> [Task: 1600] Monitoring
| |-- [Event: 20] Demand Action (Force new measures) --> [Task: 1300] Measure Definition
|
|- [Task: 1600] Monitoring
| Team: Risk Owner (Operational Unit)
| Description:
| Continuous surveillance of the risk and the effectiveness of measures. Periodic review (e.g., quarterly).
| |-- [Event: 10] Report: No Change (Keep monitoring) --> [Task: 1600] Monitoring
| |-- [Event: 20] Risk Changed (Values or measures changed) --> [Task: 1200] Gross Assessment
| |-- [Event: 30] Risk Obsolete (Risk no longer exists) --> [Task: 1800] Closure Review
|
|- [Task: 1800] Closure Review
| Team: Central Risk Management
| Description:
| Final check if the risk can really be closed.
| |-- [Event: 10] Close Risk (Archive) --> [Task: 1900] Archived
| |-- [Event: 20] Deny Closure (Keep active) --> [Task: 1600] Monitoring
|
|- [Task: 1900] Archived
| Team: System
| Description:
| Risk is closed but kept for audit trails and historical data analysis.
| |-- [Event: 10] Reactivate --> [Task: 1100] Validation
|
END
|
|- [Task: 1990] Deleted

View file

@ -1,197 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowmodelversion" type="xs:string">
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
</imixs:item>
<imixs:item name="txtfieldmapping" type="xs:string">
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
</imixs:item>
<imixs:item name="txttimefieldmapping" type="xs:string">
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
</imixs:item>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
<bpmn2:documentation id="documentation_3xKpCQ"/>
</bpmn2:participant>
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
</bpmn2:collaboration>
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
<bpmn2:lane id="Lane_1" name="Team">
<bpmn2:documentation id="documentation_gvQWYQ"/>
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="StartEvent_1" name="Start">
<bpmn2:documentation id="documentation_IUTaAQ"/>
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
<bpmn2:extensionElements>
<imixs:item name="txteditorid" type="xs:string">
<imixs:value><![CDATA[form_basic]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:string">
<imixs:value><![CDATA[true]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
<imixs:item name="namownershipnames" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddreadaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="namaddwriteaccess" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[$Editor]]></imixs:value>
<imixs:value><![CDATA[process.assist]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[process.assist]]></imixs:value>
<imixs:value><![CDATA[process.team]]></imixs:value>
<imixs:value><![CDATA[process.manager]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="Documentation_2"/>
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:endEvent id="EndEvent_2" name="End">
<bpmn2:documentation id="documentation_mHDfBQ"/>
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
<bpmn2:documentation id="documentation_RKidfg"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
<bpmn2:documentation id="documentation_V7pFuw"/>
</bpmn2:sequenceFlow>
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
<bpmn2:documentation id="documentation_e2Geig"/>
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
<bpmn2:documentation id="documentation_d1EdlQ"/>
</bpmn2:sequenceFlow>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_imRbaw"/>
<bpmn2:extensionElements>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
</bpmn2:process>
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
<bpmn2:message id="message_1" name="Message 1">
<bpmn2:documentation id="documentation_lq3hSg"/>
</bpmn2:message>
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
<dc:Bounds height="230.0" width="4430.0" x="130.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_30">
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
<di:waypoint x="273.0" y="155.0"/>
<di:waypoint x="367.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
<di:waypoint x="600.0" y="155.0"/>
<di:waypoint x="697.0" y="155.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
<di:waypoint x="403.0" y="155.0"/>
<di:waypoint x="490.0" y="155.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>
</bpmndi:BPMNLabelStyle>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View file

@ -1,146 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.openbpmn" exporterVersion="1.0.0" targetNamespace="http://open-bpmn.org">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowmodelversion" type="xs:string">
<imixs:value><![CDATA[default-en-1.0]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApproverPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.MailPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
</imixs:item>
<imixs:item name="txtfieldmapping" type="xs:string">
<imixs:value><![CDATA[Creator|$creator]]></imixs:value>
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
<imixs:value><![CDATA[Editor|$editor]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:process id="process_1" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_dIsJlQ"/>
<bpmn2:extensionElements>
<open-bpmn:auto-align>true</open-bpmn:auto-align>
</bpmn2:extensionElements>
<bpmn2:task id="task_DzBmHg" imixs:processid="100" name="Approve">
<bpmn2:documentation id="documentation_Dz7pPQ"/>
<bpmn2:incoming>sequenceFlow_3VLCbQ</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_cE44xg</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="sequenceFlow_3VLCbQ" sourceRef="event_BQQVcw" targetRef="task_DzBmHg">
<bpmn2:documentation id="documentation_Ib3jJg"/>
</bpmn2:sequenceFlow>
<bpmn2:task id="task_Qx2B4g" imixs:processid="200" name="Send">
<bpmn2:extensionElements/>
<bpmn2:documentation id="documentation_rvNWnQ"/>
<bpmn2:incoming>sequenceFlow_cE44xg</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_Sl9ddA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="sequenceFlow_cE44xg" sourceRef="task_DzBmHg" targetRef="task_Qx2B4g">
<bpmn2:documentation id="documentation_aElYrg"/>
</bpmn2:sequenceFlow>
<bpmn2:dataStoreReference id="dataStoreReference_7e3Lqw" name="Data Store">
<bpmn2:documentation id="documentation_7z4JLw"/>
</bpmn2:dataStoreReference>
<bpmn2:association id="association_iA0M8A" sourceRef="task_Qx2B4g" targetRef="dataStoreReference_7e3Lqw">
<bpmn2:documentation id="documentation_UrXC7A"/>
</bpmn2:association>
<bpmn2:dataObject id="dataObject_gtbRDw" imixs:datatype="prompt-data" name="Data">
<bpmn2:documentation id="documentation_0uxQUw"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<PromptDefinition>
<prompt_options>{}</prompt_options>
<prompt><![CDATA[<itemvalue>request.subject</itemvalue>
<FILECONTEXT>^.+\.eml$</FILECONTEXT>
]]]]><![CDATA[>
</prompt>
<loglevel>FINE</loglevel>
</PromptDefinition> ]]></bpmn2:documentation>
</bpmn2:dataObject>
<bpmn2:association id="association_lWHmDQ" sourceRef="task_DzBmHg" targetRef="dataObject_gtbRDw">
<bpmn2:documentation id="documentation_Fj4EFA"/>
</bpmn2:association>
<bpmn2:association id="association_pNef4Q" sourceRef="event_BQQVcw" targetRef="dataStoreReference_7e3Lqw">
<bpmn2:documentation id="documentation_pbD1Sw"/>
</bpmn2:association>
<bpmn2:startEvent id="event_BQQVcw" name="Start">
<bpmn2:documentation id="documentation_KSXkdw"/>
<bpmn2:outgoing>association_pNef4Q</bpmn2:outgoing>
<bpmn2:outgoing>sequenceFlow_3VLCbQ</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:endEvent id="event_uRSh7g" name="Completed">
<bpmn2:documentation id="documentation_uzqyIA"/>
<bpmn2:incoming>sequenceFlow_Sl9ddA</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="sequenceFlow_Sl9ddA" sourceRef="task_Qx2B4g" targetRef="event_uRSh7g">
<bpmn2:documentation id="documentation_SpLy3Q"/>
</bpmn2:sequenceFlow>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="OpenBPMN Diagram">
<bpmndi:BPMNPlane bpmnElement="process_1" id="BPMNPlane_d1zbGg">
<bpmndi:BPMNShape bpmnElement="task_DzBmHg" id="BPMNShape_06Te5Q">
<dc:Bounds height="50.0" width="110.0" x="200.0" y="40.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_Qx2B4g" id="BPMNShape_yer4kw">
<dc:Bounds height="50.0" width="110.0" x="450.0" y="40.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="dataStoreReference_7e3Lqw" id="BPMNShape_xwZRRA">
<dc:Bounds height="50.0" width="50.0" x="520.0" y="180.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_RaeA2w">
<dc:Bounds height="20.0" width="100.0" x="495.0" y="230.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="dataObject_gtbRDw" id="BPMNShape_31X79A">
<dc:Bounds height="50.0" width="35.0" x="270.0" y="150.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_bCydww">
<dc:Bounds height="20.0" width="100.0" x="237.5" y="205.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_BQQVcw" id="BPMNShape_aIKvbQ">
<dc:Bounds height="36.0" width="36.0" x="57.0" y="47.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_b5BxyA">
<dc:Bounds height="20.0" width="100.0" x="25.0" y="86.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_uRSh7g" id="BPMNShape_pDh8Gw">
<dc:Bounds height="36.0" width="36.0" x="657.0" y="47.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_c4C4GQ">
<dc:Bounds height="20.0" width="100.0" x="625.0" y="86.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_3VLCbQ" id="BPMNEdge_lrjXGw" sourceElement="BPMNShape_aIKvbQ" targetElement="BPMNShape_06Te5Q">
<di:waypoint x="93.0" y="65.0"/>
<di:waypoint x="200.0" y="65.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_cE44xg" id="BPMNEdge_cZ0SNA" sourceElement="BPMNShape_06Te5Q" targetElement="BPMNShape_yer4kw">
<di:waypoint x="310.0" y="65.0"/>
<di:waypoint x="450.0" y="65.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_iA0M8A" id="BPMNEdge_xP9rlQ" sourceElement="BPMNShape_yer4kw" targetElement="BPMNShape_xwZRRA">
<di:waypoint x="504.0" y="90.0"/>
<di:waypoint x="504.0" y="137.0"/>
<di:waypoint x="540.0" y="137.0"/>
<di:waypoint x="540.0" y="180.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_lWHmDQ" id="BPMNEdge_kg3SHw" sourceElement="BPMNShape_06Te5Q" targetElement="BPMNShape_31X79A">
<di:waypoint x="254.0" y="90.0"/>
<di:waypoint x="254.0" y="174.0"/>
<di:waypoint x="270.0" y="174.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_pNef4Q" id="BPMNEdge_PH7UMQ" sourceElement="BPMNShape_aIKvbQ" targetElement="BPMNShape_xwZRRA">
<di:waypoint x="75.0" y="83.0"/>
<di:waypoint x="75.0" y="243.0"/>
<di:waypoint x="544.0" y="243.0"/>
<di:waypoint x="544.0" y="230.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Sl9ddA" id="BPMNEdge_KkWFiA" sourceElement="BPMNShape_yer4kw" targetElement="BPMNShape_pDh8Gw">
<di:waypoint x="560.0" y="65.0"/>
<di:waypoint x="657.0" y="65.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 62 KiB

View file

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
<defs>
</defs>
<g transform="scale(1) translate(0,0)">
<g class="graph-content">
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
<defs>
<clipPath id="task_DzBmHg_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #00000024; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
100</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Approve </tspan>
</text>
</g>
</g>
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
<defs>
<clipPath id="task_Qx2B4g_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #00000024; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
200</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Send </tspan>
</text>
</g>
</g>
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
<g class="symbol">
<path d="" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Start </tspan>
</text>
</g>
</g>
</g>
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #00000024; stroke-width: 3px;"/>
<g class="symbol">
<path d="" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Completed </tspan>
</text>
</g>
</g>
</g>
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;">
<path d="&#10; M 0,0 &#10; L 25,0&#10; L 35,10&#10; L 35,50&#10; L 0,50&#10; Z" fill="none" stroke="#00000024" stroke-width="1.5" style="fill: #00000024;"/>
<g class="symbol">
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z&#10; M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z&#10; M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
</g>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data </tspan>
</text>
</g>
</g>
</g>
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
<path d="M0 0 L0 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
<path d="M50 0 L50 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#00000024" stroke-width="1.5"/>
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#00000024" stroke-width="1.5"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data Store </tspan>
</text>
</g>
</g>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180&#10; 200 65) translate(200 65&#10; )"/>
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180&#10; 450 65) translate(450 65&#10; )"/>
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180&#10; 657 65) translate(657 65&#10; )"/>
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
<defs>
</defs>
<g transform="scale(1) translate(0,0)">
<g class="graph-content">
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
<defs>
<clipPath id="task_DzBmHg_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #ffffff24; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
100</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Approve </tspan>
</text>
</g>
</g>
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
<defs>
<clipPath id="task_Qx2B4g_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #ffffff24; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
200</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Send </tspan>
</text>
</g>
</g>
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
<g class="symbol">
<path d="" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Start </tspan>
</text>
</g>
</g>
</g>
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff24; stroke-width: 3px;"/>
<g class="symbol">
<path d="" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Completed </tspan>
</text>
</g>
</g>
</g>
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;">
<path d="&#10; M 0,0 &#10; L 25,0&#10; L 35,10&#10; L 35,50&#10; L 0,50&#10; Z" fill="none" stroke="#ffffff24" stroke-width="1.5" style="fill: #ffffff24;"/>
<g class="symbol">
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z&#10; M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z&#10; M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
</g>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data </tspan>
</text>
</g>
</g>
</g>
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
<path d="M0 0 L0 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
<path d="M50 0 L50 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#ffffff24" stroke-width="1.5"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data Store </tspan>
</text>
</g>
</g>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180&#10; 200 65) translate(200 65&#10; )"/>
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180&#10; 450 65) translate(450 65&#10; )"/>
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180&#10; 657 65) translate(657 65&#10; )"/>
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
<defs>
</defs>
<g transform="scale(1) translate(0,0)">
<g class="graph-content">
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
<defs>
<clipPath id="task_DzBmHg_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #ffffff0a; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
100</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Approve </tspan>
</text>
</g>
</g>
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
<defs>
<clipPath id="task_Qx2B4g_clip_path">
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 &#10; -3,3h-100q-3,0 -3,-3z "/>
</clipPath>
</defs>
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 &#10; -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
<g class="extension">
<text style="fill: #ffffff0a; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
200</text>
</g>
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
<tspan dy="10" x="0">Send </tspan>
</text>
</g>
</g>
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
<g class="symbol">
<path d="" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Start </tspan>
</text>
</g>
</g>
</g>
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff0a; stroke-width: 3px;"/>
<g class="symbol">
<path d="" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Completed </tspan>
</text>
</g>
</g>
</g>
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;">
<path d="&#10; M 0,0 &#10; L 25,0&#10; L 35,10&#10; L 35,50&#10; L 0,50&#10; Z" fill="none" stroke="#ffffff0a" stroke-width="1.5" style="fill: #ffffff0a;"/>
<g class="symbol">
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z&#10; M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z&#10; M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
</g>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data </tspan>
</text>
</g>
</g>
</g>
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
<path d="M0 0 L0 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
<path d="M50 0 L50 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#ffffff0a" stroke-width="1.5"/>
</g>
</g>
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
<tspan dy="10" x="0">Data Store </tspan>
</text>
</g>
</g>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180&#10; 200 65) translate(200 65&#10; )"/>
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180&#10; 450 65) translate(450 65&#10; )"/>
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180&#10; 657 65) translate(657 65&#10; )"/>
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
</g>
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,494 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DYNAMIXS.AI - Die TRUSTED Enterprise AI Platform</title>
<style>
/*
*************************************************
* CSS-GRUNDLAGEN (Zum schnellen Testen integriert) *
*************************************************
*/
:root {
--color-primary: #007bff;
/* Starkes Blau */
--color-secondary: #28a745;
/* Akzent Grün/Akzent */
--color-dark: #212529;
--color-light: #f8f9fa;
--font-family: 'Inter', sans-serif;
--section-padding: 80px 0;
}
body {
font-family: var(--font-family);
line-height: 1.6;
margin: 0;
padding-top: 60px;
/* Platz für die Fixed-Navigation */
color: var(--color-dark);
background-color: white;
}
h1,
h2,
h3 {
line-height: 1.2;
font-weight: 800;
margin-bottom: 20px;
}
a {
color: var(--color-primary);
text-decoration: none;
transition: color 0.3s;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
section {
padding: var(--section-padding);
scroll-margin-top: 60px;
/* Für smooth scrolling */
}
/* --- Navigation --- */
.header-nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.nav-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
}
.logo {
font-size: 1.5em;
font-weight: bold;
color: var(--color-dark);
}
.nav-menu ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
.nav-menu ul li a {
padding: 10px 15px;
display: block;
font-weight: 600;
color: var(--color-dark);
}
.nav-menu ul li a:hover {
color: var(--color-primary);
}
/* --- CTAs --- */
.btn {
display: inline-block;
padding: 12px 25px;
margin-top: 10px;
border-radius: 5px;
text-transform: uppercase;
font-weight: 600;
transition: background-color 0.3s;
text-align: center;
}
.btn-primary {
background-color: var(--color-primary);
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-secondary {
background-color: transparent;
color: var(--color-primary);
border: 2px solid var(--color-primary);
}
.btn-secondary:hover {
background-color: var(--color-primary);
color: white;
}
/* --- Sektion: Hero/Home --- */
#home {
background-color: var(--color-light);
text-align: center;
padding: 100px 0;
}
#home h1 {
font-size: 3em;
margin-bottom: 10px;
color: var(--color-dark);
}
#home .subtitle {
font-size: 1.5em;
font-weight: 400;
margin-bottom: 40px;
color: #6c757d;
}
.cta-group .btn {
margin: 0 10px;
}
/* --- Sektion: Problem (Kontrast-Sektion) --- */
#problem {
background-color: var(--color-dark);
color: white;
text-align: center;
}
#problem h2 {
color: white;
}
#problem ul {
list-style: none;
padding: 0;
display: flex;
justify-content: center;
gap: 40px;
flex-wrap: wrap;
}
#problem ul li {
max-width: 250px;
text-align: left;
padding: 20px;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 8px;
}
/* --- Sektion: Features (Grid) --- */
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 40px;
margin-top: 40px;
}
.feature-card {
background-color: var(--color-light);
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
.feature-card h3 {
color: var(--color-primary);
}
/* --- Sektion: Prozess (Linearer Ablauf) --- */
.process-step {
display: flex;
align-items: flex-start;
margin-bottom: 30px;
}
.step-number {
font-size: 2em;
font-weight: bold;
color: var(--color-secondary);
margin-right: 20px;
}
.step-content h3 {
margin-top: 0;
color: var(--color-primary);
}
/* --- Sektion: Ergebnisse (Metriken/Testimonials) --- */
.metric-grid {
display: flex;
justify-content: space-around;
text-align: center;
margin-top: 40px;
}
.metric strong {
display: block;
font-size: 3em;
color: var(--color-primary);
line-height: 1;
}
.testimonial-card {
background-color: var(--color-light);
padding: 30px;
border-left: 5px solid var(--color-secondary);
margin-top: 30px;
}
/* --- Footer --- */
footer {
background-color: var(--color-dark);
color: white;
padding: 40px 0;
text-align: center;
font-size: 0.9em;
}
footer a {
color: white;
margin: 0 10px;
}
/* --- Media Queries für Responsivität --- */
@media (max-width: 768px) {
.nav-menu ul {
display: none;
/* Mobile Navigation vereinfacht (Hamburger-Menü würde hier folgen) */
}
.nav-content {
justify-content: center;
}
body {
padding-top: 50px;
}
.header-nav {
height: 50px;
}
#home h1 {
font-size: 2.5em;
}
.metric-grid {
flex-direction: column;
gap: 30px;
}
.cta-group {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>
</head>
<body>
<header class="header-nav">
<div class="container nav-content">
<div class="logo">DYNAMIXS.AI</div>
<nav class="nav-menu">
<ul>
<li><a href="#home">Start</a></li>
<li><a href="#plattform">Plattform</a></li>
<li><a href="#prozess">Prozess</a></li>
<li><a href="#ergebnisse">Erfolge</a></li>
<li><a href="#kontakt" class="btn btn-primary">Demo</a></li>
</ul>
</nav>
</div>
</header>
<section id="home" class="container">
<h1>Ihre Geschäftsprozesse sind einzigartig.<br>Unsere KI versteht sie.</h1>
<p class="subtitle">Die **TRUSTED Enterprise AI Platform** – Modellierung, Verbesserung und Automatisierung
Ihrer Prozesse, geerdet in Ihrer Business-Realität.</p>
<div class="cta-group">
<a href="#plattform" class="btn btn-primary">Platform kennenlernen</a>
<a href="#kontakt" class="btn btn-secondary">Experten sprechen</a>
</div>
</section>
<section id="problem">
<div class="container">
<h2>Warum KI allein nicht genug ist</h2>
<p>Ohne den Kontext Ihrer Abläufe bleibt KI eine Black Box. Die häufigsten Herausforderungen:</p>
<ul>
<li>
<i class="fas fa-sitemap"></i>
<h3>Verstreute Workflows</h3>
<p>Komplexe Abläufe sind über viele Systeme verteilt, Tools halten nicht Schritt.</p>
</li>
<li>
<i class="fas fa-database"></i>
<h3>Datensilos</h3>
<p>Wichtige Informationen sind isoliert, was Entscheidungen verlangsamt und die Zuverlässigkeit
mindert.</p>
</li>
<li>
<i class="fas fa-lock"></i>
<h3>Sicherheitsrisiken</h3>
<p>Compliance- und Sicherheitsauflagen limitieren den Einsatz externer, unkontrollierter KI.</p>
</li>
</ul>
</div>
</section>
<section id="plattform" class="container">
<h2>Was DYNAMIXS.AI **anders** macht</h2>
<p class="subtitle">Wir starten mit Ihrer Business-Realität. Die DYNAMIXS.AI Plattform ist Ihre **Process
Context Engine**:</p>
<p>Ihre Workflows, Regeln, Dokumente und das Expertenwissen Ihrer Teams werden zusammengeführt, um der KI den
notwendigen Kontext zu liefern. Dadurch wird KI **präzise, geschäftsreif und vertrauenswürdig**.</p>
<img src="placeholder-grafik-context-engine.svg" alt="Visuelle Darstellung der Process Context Engine"
style="width: 100%; max-width: 600px; display: block; margin: 40px auto;">
<a href="#features" class="btn btn-primary">Mehr zu AI Modeling</a>
</section>
<section id="features" class="container">
<h2>Drei Säulen für Ihren Erfolg</h2>
<div class="feature-grid">
<div class="feature-card">
<i class="fas fa-handshake fa-3x"></i>
<h3>Start mit Ihrer Geschäftsrealität</h3>
<p>Wir modellieren Prozesse, Daten und Regeln exakt so, wie sie existieren. Ihre individuelle Logik ist
die Basis für präzise KI-Aktionen.</p>
<a href="#">Mehr erfahren &rarr;</a>
</div>
<div class="feature-card">
<i class="fas fa-robot fa-3x"></i>
<h3>AI transformiert Ihre Prozesse</h3>
<p>Ihre Workflows bilden den Rahmen für KI-gesteuerte Entscheidungen: **Smart, Secure und Trusted.** Das
System lernt mit jedem Workflow.</p>
<a href="#">AI Modeling ansehen &rarr;</a>
</div>
<div class="feature-card">
<i class="fas fa-cogs fa-3x"></i>
<h3>Effiziente Anpassung mit Templates</h3>
<p>Vordefinierte Bausteine für Finance, HR und Logistik ermöglichen eine schnelle, kosteneffiziente
Implementierung in Stunden statt Wochen.</p>
<a href="#">Zur Template Library &rarr;</a>
</div>
</div>
</section>
<section id="prozess" class="container" style="background-color: var(--color-light);">
<h2>In 4 Schritten zur Trusted AI Platform</h2>
<p>Von der Vision zur Implementierung – schnell und strukturiert.</p>
<div class="process-flow">
<div class="process-step">
<div class="step-number">1</div>
<div class="step-content">
<h3>Capture your business reality</h3>
<p>Ihre Prozesse, Daten und Regeln werden in einem Living Model abgebildet.</p>
</div>
</div>
<div class="process-step">
<div class="step-number">2</div>
<div class="step-content">
<h3>Build the workflow model</h3>
<p>Eine erste lauffähige Version Ihres Systems ist innerhalb von Stunden einsatzbereit.</p>
</div>
</div>
<div class="process-step">
<div class="step-number">3</div>
<div class="step-content">
<h3>Customize with templates</h3>
<p>Fertige Komponenten verkürzen die Entwicklungszeit und beschleunigen die Implementierung.</p>
</div>
</div>
<div class="process-step">
<div class="step-number">4</div>
<div class="step-content">
<h3>Deploy, learn, improve</h3>
<p>Nach dem Live-Gang beginnt die kontinuierliche Optimierung durch gesammelte Prozessdaten.</p>
</div>
</div>
</div>
</section>
<section id="architektur" class="container">
<h2>Enterprise-Ready Architektur</h2>
<p>Ein Technologie-Stack, geformt durch zwei Jahrzehnte Enterprise-Projekte, auf den Sie sich verlassen können:
</p>
<ul>
<li>**Skalierbar:** Event-driven, BPMN-basiert, Cloud-native und API-first.</li>
<li>**Geschützt:** Daten sind verschlüsselt, auditierbar und DSGVO-konform.</li>
<li>**Bewährt:** Erfolgreich im Einsatz in Logistik, HR, Finance und Government.</li>
</ul>
<a href="#" class="btn btn-secondary">Architektur im Detail ansehen</a>
</section>
<section id="ergebnisse" class="container" style="background-color: var(--color-light);">
<h2>Messbare Erfolge in realen Unternehmen</h2>
<div class="metric-grid">
<div class="metric">
<strong>2</strong>
<p>Wochen bis zur vollen Integration in vielen Kundenfällen.</p>
</div>
<div class="metric">
<strong>5,000+</strong>
<p>Transaktionen und 95 Modelle bei einer Steuerberatung.</p>
</div>
<div class="metric">
<strong>2</strong>
<p>Stunden bis zum ersten lauffähigen Modell.</p>
</div>
</div>
<div class="testimonial-card">
<p>“Unglaublich, wie schnell wir unsere Geschäftsprozesse implementiert haben. Die Ergebnisse fließen direkt
in unser ERP.”</p>
<small>— Kunde, Finance</small>
</div>
<a href="#" class="btn btn-primary" style="margin-top: 40px;">Alle Erfolgsstories &rarr;</a>
</section>
<section id="kontakt" class="container" style="text-align: center;">
<h2>Ready to see how?</h2>
<p class="subtitle">Nutzen Sie das ungenutzte Intelligenzpotenzial Ihrer Workflows. Wir zeigen Ihnen, wie.</p>
<a href="#" class="btn btn-primary btn-lg" style="font-size: 1.2em;">Jetzt Beratungstermin vereinbaren</a>
<p style="margin-top: 20px;">Oder rufen Sie uns an: +49 (0) XXXX / XXXXXX</p>
</section>
<footer>
<div class="container">
<div class="logo">DYNAMIXS.AI</div>
<p>© 2025 DYNAMIXS.AI | Alle Rechte vorbehalten.</p>
<p>
<a href="#">Kontakt</a>
<a href="#">Legal / Impressum</a>
<a href="#">Datenschutz</a>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,156 +0,0 @@
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>dynamixs-ai</artifactId>
<groupId>ai.dynamixs</groupId>
<version>1.0.2</version>
</parent>
<artifactId>dynamixs-ai-mcp</artifactId>
<packaging>jar</packaging>
<name>Dynamixs AI MCP Server Library</name>
<build>
<plugins>
<!-- use JDK settings for compiling -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.source}</source>
<target>${java.target}</target>
</configuration>
</plugin>
<!-- Testing JUnit 5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<!-- issue #572
hack for:
https://stackoverflow.com/questions/75116023/unable-to-make-protected-final-java-lang-class-java-lang-classloader-defineclass
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<argLine>
--add-opens java.base/java.lang=ALL-UNNAMED
</argLine>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Jakarta EE -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakarta.version}</version>
<scope>provided</scope>
</dependency>
<!-- Microprofile -->
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>${microprofile.version}</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<!-- Imixs Workflow -->
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-core</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-engine</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-jax-rs</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<dependency>
<groupId>org.imixs.workflow</groupId>
<artifactId>imixs-workflow-faces</artifactId>
<type>jar</type>
<version>${org.imixs.workflow.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>jakarta.json</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View file

@ -1,315 +0,0 @@
package ai.dynamixs.mcp;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonString;
/**
* Represents an MCP Resource based on Imixs-Workflow BPMN models.
*
* MCP Resources represent entities that can be read by the MCP client. Each
* resource corresponds to a workflow task/event combination.
*/
public class MCPResource implements Serializable {
private static final long serialVersionUID = 1L;
// MCP Standard Fields
private String uri; // Resource URI
private String name; // Human-readable name
private String description; // Resource description
private String mimeType; // MIME type of the resource
private Map<String, Object> annotations; // Additional metadata
// Imixs-specific fields
private String modelVersion;
private int taskId;
private int eventId;
// Constructors
public MCPResource() {
this.annotations = new HashMap<>();
}
public MCPResource(String modelVersion, int taskId, int eventId) {
this();
this.modelVersion = modelVersion;
this.taskId = taskId;
this.eventId = eventId;
this.uri = createResourceUri(modelVersion, taskId, eventId);
}
/**
* Creates a resource URI from Imixs workflow components
*/
public static String createResourceUri(String modelVersion, int taskId, int eventId) {
if (modelVersion == null || modelVersion.trim().isEmpty()) {
throw new IllegalArgumentException("Model version cannot be null or empty");
}
return String.format("imixs://workflow/%s/%d/%d", modelVersion, taskId, eventId);
}
/**
* Parses model version from URI
*/
public String getModelVersionFromUri() {
if (uri == null || !uri.startsWith("imixs://workflow/")) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
String path = uri.substring("imixs://workflow/".length());
String[] parts = path.split("/");
if (parts.length < 3) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
return parts[0];
}
/**
* Parses task ID from URI
*/
public int getTaskIdFromUri() {
if (uri == null || !uri.startsWith("imixs://workflow/")) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
String path = uri.substring("imixs://workflow/".length());
String[] parts = path.split("/");
if (parts.length < 3) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
try {
return Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid task ID in resource URI: " + uri, e);
}
}
/**
* Parses event ID from URI
*/
public int getEventIdFromUri() {
if (uri == null || !uri.startsWith("imixs://workflow/")) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
String path = uri.substring("imixs://workflow/".length());
String[] parts = path.split("/");
if (parts.length < 3) {
throw new IllegalStateException("Invalid resource URI format: " + uri);
}
try {
return Integer.parseInt(parts[2]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid event ID in resource URI: " + uri, e);
}
}
/**
* Converts this resource to MCP JSON format
*/
public JsonObject toJsonObject() {
JsonObjectBuilder builder = Json.createObjectBuilder()
.add("uri", uri != null ? uri : "")
.add("name", name != null ? name : "")
.add("description", description != null ? description : "");
if (mimeType != null) {
builder.add("mimeType", mimeType);
}
// Annotations object
if (annotations != null && !annotations.isEmpty()) {
JsonObjectBuilder annotationsBuilder = Json.createObjectBuilder();
annotations.forEach((key, value) -> {
if (value instanceof String) {
annotationsBuilder.add(key, (String) value);
} else if (value instanceof Number) {
annotationsBuilder.add(key, ((Number) value).doubleValue());
} else if (value instanceof Boolean) {
annotationsBuilder.add(key, (Boolean) value);
} else if (value != null) {
annotationsBuilder.add(key, value.toString());
}
});
builder.add("annotations", annotationsBuilder.build());
}
return builder.build();
}
/**
* Creates an MCPResource from a JsonObject
*/
public static MCPResource fromJsonObject(JsonObject jsonObject) {
MCPResource resource = new MCPResource();
resource.setUri(jsonObject.getString("uri", ""));
resource.setName(jsonObject.getString("name", ""));
resource.setDescription(jsonObject.getString("description", ""));
if (jsonObject.containsKey("mimeType")) {
resource.setMimeType(jsonObject.getString("mimeType"));
}
// Annotations
if (jsonObject.containsKey("annotations")) {
JsonObject annotationsObject = jsonObject.getJsonObject("annotations");
Map<String, Object> annotations = new HashMap<>();
annotationsObject.forEach((key, value) -> {
switch (value.getValueType()) {
case STRING:
annotations.put(key, ((JsonString) value).getString());
break;
case NUMBER:
annotations.put(key, ((jakarta.json.JsonNumber) value).doubleValue());
break;
case TRUE:
annotations.put(key, Boolean.TRUE);
break;
case FALSE:
annotations.put(key, Boolean.FALSE);
break;
default:
annotations.put(key, value.toString());
}
});
resource.setAnnotations(annotations);
}
return resource;
}
/**
* Validates this resource for MCP compliance
*/
public boolean isValid() {
if (uri == null || uri.trim().isEmpty()) {
return false;
}
if (name == null || name.trim().isEmpty()) {
return false;
}
// Validate URI format
try {
getModelVersionFromUri();
getTaskIdFromUri();
getEventIdFromUri();
} catch (Exception e) {
return false;
}
return true;
}
// Getters and Setters
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
public Map<String, Object> getAnnotations() {
return annotations;
}
public void setAnnotations(Map<String, Object> annotations) {
this.annotations = annotations != null ? annotations : new HashMap<>();
}
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public int getTaskId() {
return taskId;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
// Convenience methods for annotations
public void addAnnotation(String key, Object value) {
if (annotations == null) {
annotations = new HashMap<>();
}
annotations.put(key, value);
}
public String getAnnotationString(String key) {
Object value = annotations != null ? annotations.get(key) : null;
return value != null ? value.toString() : null;
}
public Boolean getAnnotationBoolean(String key) {
Object value = annotations != null ? annotations.get(key) : null;
if (value instanceof Boolean) {
return (Boolean) value;
}
return null;
}
@Override
public String toString() {
return String.format("MCPResource{uri='%s', name='%s', modelVersion='%s', taskId=%d, eventId=%d}",
uri, name, modelVersion, taskId, eventId);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
MCPResource that = (MCPResource) obj;
return uri != null ? uri.equals(that.uri) : that.uri == null;
}
@Override
public int hashCode() {
return uri != null ? uri.hashCode() : 0;
}
}

View file

@ -1,434 +0,0 @@
/*******************************************************************************
* Imixs Workflow
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Project:
* http://www.imixs.org
* http://java.net/projects/imixs-workflow
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika - Software Developer
*******************************************************************************/
package ai.dynamixs.mcp;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.imixs.workflow.ItemCollection;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
/**
* The MCPRestService provides Model Context Protocol (MCP) endpoints for
* accessing workflow resources and tools.
*
* @author rsoika
*/
@Named
@RequestScoped
@Path("/mcp/")
@Produces({ MediaType.APPLICATION_JSON })
public class MCPRestService implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(MCPRestService.class.getSimpleName());
@Context
UriInfo uriInfo;
@Inject
MCPService mcpService;
/**
* MCP JSON-RPC 2.0 Endpoint All MCP protocol methods are handled here URL:
* /mcp/v1
*/
@POST
@Path("/v1")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response handleJsonRpcRequest(JsonObject request) {
try {
// Validate JSON-RPC 2.0 structure
if (!isValidJsonRpcRequest(request)) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(buildJsonRpcError(-32600, "Invalid Request", null))
.build();
}
String method = request.getString("method");
Object id = request.get("id");
JsonObject params = request.containsKey("params") ? request.getJsonObject("params") : null;
// Route to appropriate MCP method
switch (method) {
case "initialize":
return handleInitialize(id, params);
case "resources/list":
return handleResourcesList(id, params);
case "resources/read":
return handleResourcesRead(id, params);
case "tools/list":
return handleToolsList(id, params);
case "tools/call":
return handleToolsCall(id, params);
default:
return Response.status(Response.Status.NOT_FOUND)
.entity(buildJsonRpcError(-32601, "Method not found", id))
.build();
}
} catch (Exception e) {
logger.severe("Error processing MCP JSON-RPC request: " + e.getMessage());
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", null))
.build();
}
}
/**
* Handle MCP initialize method
*/
private Response handleInitialize(Object id, JsonObject params) {
try {
// Build server capabilities
JsonObject capabilities = Json.createObjectBuilder()
.add("resources", Json.createObjectBuilder()
.add("subscribe", false)
.add("listChanged", false)
.build())
.add("tools", Json.createObjectBuilder().build())
.add("logging", Json.createObjectBuilder().build())
.build();
// Build server information
JsonObject serverInfo = Json.createObjectBuilder()
.add("name", "Dynamixs.AI MCP Server")
.add("version", "1.0.0")
.build();
JsonObject result = Json.createObjectBuilder()
.add("protocolVersion", "2024-11-05")
.add("capabilities", capabilities)
.add("serverInfo", serverInfo)
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", result)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in initialize: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", id))
.build();
}
}
/**
* Handle MCP resources/list method
*/
private Response handleResourcesList(Object id, JsonObject params) {
try {
List<MCPResource> resources = mcpService.parseResources();
List<MCPResource> validResources = resources.stream()
.filter(MCPResource::isValid)
.collect(Collectors.toList());
JsonArray resourcesArray = validResources.stream()
.map(MCPResource::toJsonObject)
.collect(Json::createArrayBuilder,
JsonArrayBuilder::add,
JsonArrayBuilder::addAll)
.build();
JsonObject result = Json.createObjectBuilder()
.add("resources", resourcesArray)
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", result)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in resources/list: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", id))
.build();
}
}
/**
* Handle MCP resources/read method
*/
private Response handleResourcesRead(Object id, JsonObject params) {
try {
if (params == null || !params.containsKey("uri")) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(buildJsonRpcError(-32602, "Invalid params: missing uri", id))
.build();
}
String uri = params.getString("uri");
String content = mcpService.readResource(uri);
JsonObject result = Json.createObjectBuilder()
.add("contents", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("uri", uri)
.add("mimeType", "text/plain")
.add("text", content)
.build())
.build())
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", result)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in resources/read: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32001, "Resource not found", id))
.build();
}
}
/**
* Handle MCP tools/list method
*/
private Response handleToolsList(Object id, JsonObject params) {
try {
List<MCPTool> tools = mcpService.parseTools();
List<MCPTool> validTools = tools.stream()
.filter(MCPTool::isValid)
.collect(Collectors.toList());
JsonArray toolsArray = validTools.stream()
.map(MCPTool::toJsonObject)
.collect(Json::createArrayBuilder,
JsonArrayBuilder::add,
JsonArrayBuilder::addAll)
.build();
JsonObject result = Json.createObjectBuilder()
.add("tools", toolsArray)
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", result)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in tools/list: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(buildJsonRpcError(-32603, "Internal server error", id))
.build();
}
}
/**
* Handle MCP tools/call method
*/
private Response handleToolsCall(Object id, JsonObject params) {
try {
if (params == null || !params.containsKey("name")) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(buildJsonRpcError(-32602, "Invalid params: missing name", id))
.build();
}
String toolName = params.getString("name");
JsonObject arguments = params.containsKey("arguments") ? params.getJsonObject("arguments")
: Json.createObjectBuilder().build();
// Convert JSON arguments to ItemCollection
ItemCollection workitem = jsonToItemCollection(arguments);
// Execute the tool
ItemCollection result = mcpService.executeTool(toolName, workitem);
// Convert result back to JSON
JsonObject toolResult = itemCollectionToJson(result);
// Build MCP response with content array
JsonObject mcpResult = Json.createObjectBuilder()
.add("content", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "text")
.add("text", "Tool executed successfully. Result: " + toolResult.toString())
.build())
.build())
.add("isError", false)
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", mcpResult)
.build();
return Response.ok(response).build();
} catch (Exception e) {
logger.severe("Error in tools/call: " + e.getMessage());
// Return error content in MCP format
JsonObject errorResult = Json.createObjectBuilder()
.add("content", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "text")
.add("text", "Tool execution failed: " + e.getMessage())
.build())
.build())
.add("isError", true)
.build();
JsonObject response = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("id", id.toString())
.add("result", errorResult)
.build();
return Response.ok(response).build();
}
}
/**
* Validates JSON-RPC 2.0 request structure
*/
private boolean isValidJsonRpcRequest(JsonObject request) {
return request.containsKey("jsonrpc") &&
"2.0".equals(request.getString("jsonrpc")) &&
request.containsKey("method") &&
request.containsKey("id");
}
/**
* Builds a JSON-RPC 2.0 error response
*/
private JsonObject buildJsonRpcError(int code, String message, Object id) {
JsonObjectBuilder errorBuilder = Json.createObjectBuilder()
.add("code", code)
.add("message", message);
JsonObjectBuilder responseBuilder = Json.createObjectBuilder()
.add("jsonrpc", "2.0")
.add("error", errorBuilder.build());
if (id != null) {
responseBuilder.add("id", id.toString());
} else {
responseBuilder.addNull("id");
}
return responseBuilder.build();
}
/**
* Converts a JSON object to an ItemCollection
*/
private ItemCollection jsonToItemCollection(JsonObject jsonObject) {
ItemCollection itemCol = new ItemCollection();
if (jsonObject.containsKey("workitem")) {
JsonObject workitem = jsonObject.getJsonObject("workitem");
workitem.forEach((key, value) -> {
switch (value.getValueType()) {
case STRING:
itemCol.setItemValue(key, ((jakarta.json.JsonString) value).getString());
break;
case NUMBER:
itemCol.setItemValue(key, ((jakarta.json.JsonNumber) value).intValue());
break;
case TRUE:
itemCol.setItemValue(key, Boolean.TRUE);
break;
case FALSE:
itemCol.setItemValue(key, Boolean.FALSE);
break;
default:
itemCol.setItemValue(key, value.toString());
}
});
}
return itemCol;
}
/**
* Converts an ItemCollection to a JSON object
*/
private JsonObject itemCollectionToJson(ItemCollection itemCol) {
JsonObjectBuilder builder = Json.createObjectBuilder();
for (String itemName : itemCol.getItemNames()) {
Object value = itemCol.getItemValue(itemName);
if (value instanceof String) {
builder.add(itemName, (String) value);
} else if (value instanceof Integer) {
builder.add(itemName, (Integer) value);
} else if (value instanceof Double) {
builder.add(itemName, (Double) value);
} else if (value instanceof Boolean) {
builder.add(itemName, (Boolean) value);
} else if (value != null) {
builder.add(itemName, value.toString());
}
}
return builder.build();
}
}

View file

@ -1,273 +0,0 @@
package ai.dynamixs.mcp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.ModelManager;
import org.imixs.workflow.engine.ModelService;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.ModelException;
import org.imixs.workflow.exceptions.PluginException;
import org.openbpmn.bpmn.BPMNModel;
import jakarta.annotation.security.DeclareRoles;
import jakarta.annotation.security.RolesAllowed;
import jakarta.ejb.LocalBean;
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
/**
* The MCPService parses the model information to provide MCP Resources and
* Tools
*
* @author rsoika
*/
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS",
"org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
"org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS",
"org.imixs.ACCESSLEVEL.READERACCESS",
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
"org.imixs.ACCESSLEVEL.EDITORACCESS",
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
@Stateless
@LocalBean
public class MCPService {
@Inject
ModelService modelService;
@Inject
WorkflowService workflowService;
private static Logger logger = Logger.getLogger(MCPService.class.getName());
/**
* This method iterates over all models and returns a list of MCP resources
*
* The method looks for events with <imixs-ai name="RESOURCE"> tag.
*/
public List<MCPResource> parseResources() {
logger.log(Level.INFO, "├── 🔃 parsing MCP Resources....");
List<MCPResource> result = new ArrayList<>();
ModelManager modelManager = new ModelManager(workflowService);
List<String> versions = modelService.getVersions();
try {
for (String version : versions) {
logger.log(Level.INFO, "│ ├── {0}", version);
BPMNModel model = modelManager.getModel(version);
Set<String> groups = modelManager.findAllGroupsByModel(model);
for (String group : groups) {
List<ItemCollection> tasks = modelManager.findTasks(model, group);
for (ItemCollection task : tasks) {
int taskID = task.getItemValueInteger("taskid");
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
for (ItemCollection event : events) {
int eventID = event.getItemValueInteger("eventid");
// test if we have a <imixs-ai name="RESOURCE">
try {
List<ItemCollection> resourceDefinitions = workflowService.evalWorkflowResultXML(
event, "imixs-ai", "RESOURCE", null, false);
// did we found a resource?
for (ItemCollection resourceItemCol : resourceDefinitions) {
MCPResource resource = new MCPResource(version, taskID, eventID);
resource.setName(event.getItemValueString("name"));
resource.setDescription(resourceItemCol.getItemValueString("description"));
resource.setMimeType("text/plain");
// Add annotations
String tags = resourceItemCol.getItemValueString("tags");
if (tags != null && !tags.isBlank()) {
resource.addAnnotation("tags", tags);
}
String category = resourceItemCol.getItemValueString("category");
if (category != null && !category.isBlank()) {
resource.addAnnotation("category", category);
}
if (resource.isValid()) {
result.add(resource);
logger.log(Level.INFO, "│ │ ├── Resource: {0}", resource.getUri());
}
}
} catch (PluginException e) {
// no match
}
}
}
}
}
} catch (ModelException e) {
logger.log(Level.SEVERE, "Error parsing models for resources", e);
}
return result;
}
/**
* This method iterates over all models and returns a list of MCP tools
*
* The method looks for events with <imixs-ai name="TOOL"> tag.
*/
public List<MCPTool> parseTools() {
logger.log(Level.INFO, "├── 🔃 parsing MCP Tools....");
List<MCPTool> result = new ArrayList<>();
ModelManager modelManager = new ModelManager(workflowService);
List<String> versions = modelService.getVersions();
try {
for (String version : versions) {
logger.log(Level.INFO, "│ ├── {0}", version);
BPMNModel model = modelManager.getModel(version);
Set<String> groups = modelManager.findAllGroupsByModel(model);
for (String group : groups) {
List<ItemCollection> tasks = modelManager.findTasks(model, group);
for (ItemCollection task : tasks) {
int taskID = task.getItemValueInteger("taskid");
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
for (ItemCollection event : events) {
int eventID = event.getItemValueInteger("eventid");
// test if we have a <imixs-ai name="TOOL">
try {
List<ItemCollection> toolDefinitions = workflowService.evalWorkflowResultXML(
event, "imixs-ai", "TOOL", null, false);
// did we found a tool?
for (ItemCollection toolItemCol : toolDefinitions) {
MCPTool tool = new MCPTool(version, taskID, eventID);
String toolName = version + "_" + taskID + "_" + eventID;// toolItemCol.getItemValueString("name");
if (toolName != null && !toolName.isBlank()) {
tool.setName(toolName);
}
tool.setDescription(toolItemCol.getItemValueString("description"));
String tags = toolItemCol.getItemValueString("tags");
if (tags != null && !tags.isBlank()) {
String[] parts = tags.split(",\\s*");
tool.setTags(Arrays.asList(parts));
}
tool.setExamples(toolItemCol.getItemValueList("example", String.class));
if (tool.isValid()) {
result.add(tool);
logger.log(Level.INFO, "│ │ ├── Tool: {0}", tool.getName());
}
}
} catch (PluginException e) {
// no match
}
}
}
}
}
} catch (ModelException e) {
logger.log(Level.SEVERE, "Error parsing models for tools", e);
}
return result;
}
/**
* Executes a workflow tool with the given arguments
*/
public ItemCollection executeTool(String toolName, ItemCollection workitem) throws Exception {
logger.log(Level.INFO, "├── 🔧 executing MCP Tool: {0}", toolName);
// Parse tool name to extract workflow parameters
MCPTool tool = new MCPTool();
tool.setName(toolName);
String modelVersion = tool.getModelVersionFromName();
int taskId = tool.getTaskIdFromName();
int eventId = tool.getEventIdFromName();
// Set workflow parameters
workitem.setItemValue("$modelversion", modelVersion);
workitem.setItemValue("$taskid", taskId);
workitem.setItemValue("$eventid", eventId);
// Process the workitem
ItemCollection result = workflowService.processWorkItem(workitem);
logger.log(Level.INFO, "│ └── Tool execution completed");
return result;
}
/**
* Reads the content of a resource
*/
public String readResource(String uri) throws Exception {
logger.log(Level.INFO, "├── 📖 reading MCP Resource: {0}", uri);
// Parse URI to extract workflow parameters
MCPResource resource = new MCPResource();
resource.setUri(uri);
String modelVersion = resource.getModelVersionFromUri();
int taskId = resource.getTaskIdFromUri();
int eventId = resource.getEventIdFromUri();
// Create a workitem to read the resource
ItemCollection workitem = new ItemCollection();
workitem.setItemValue("$modelversion", modelVersion);
workitem.setItemValue("$taskid", taskId);
workitem.setItemValue("$eventid", eventId);
// Get the event definition to extract resource content
ModelManager modelManager = new ModelManager(workflowService);
BPMNModel model = modelManager.getModel(modelVersion);
ItemCollection event = modelManager.findEventByID(model, taskId, eventId);
if (event == null) {
throw new Exception("Event not found: " + uri);
}
// Look for resource content in the event
try {
List<ItemCollection> resourceDefinitions = workflowService.evalWorkflowResultXML(
event, "imixs-ai", "RESOURCE", null, false);
if (!resourceDefinitions.isEmpty()) {
ItemCollection resourceDef = resourceDefinitions.get(0);
String content = resourceDef.getItemValueString("content");
if (content != null && !content.isBlank()) {
return content;
}
}
} catch (PluginException e) {
// no resource definition found
}
// Fallback: return event documentation
String documentation = event.getItemValueString("documentation");
if (documentation != null && !documentation.isBlank()) {
return documentation;
}
// Last fallback: return event name and description
return String.format("Event: %s\nDescription: %s",
event.getItemValueString("name"),
event.getItemValueString("description"));
}
}

View file

@ -1,254 +0,0 @@
package ai.dynamixs.mcp;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.json.Json;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
/**
* Test endpoint for MCP server discovery and debugging Similar to A2A Agent
* Card but for MCP protocol
*
* @author rsoika
*/
@Named
@RequestScoped
@Path("/mcp/debug/")
@Produces({ MediaType.APPLICATION_JSON })
public class MCPTestEndpoint implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(MCPTestEndpoint.class.getSimpleName());
@Context
UriInfo uriInfo;
@Inject
MCPService mcpService;
/**
* MCP Server Information Endpoint (similar to A2A Agent Card) URL:
* /mcp/server-info
*/
@GET
@Path("/server-info")
public Response getServerInfo() {
try {
JsonObject serverInfo = buildServerInfo();
return Response.ok(serverInfo).build();
} catch (Exception e) {
logger.severe("Error creating MCP server info: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Json.createObjectBuilder()
.add("error", "Internal server error")
.add("message", e.getMessage())
.build())
.build();
}
}
/**
* Quick test endpoint to list all available resources URL: /mcp/test/resources
*/
@GET
@Path("/test/resources")
public Response testResources() {
try {
List<MCPResource> resources = mcpService.parseResources();
JsonArrayBuilder resourcesBuilder = Json.createArrayBuilder();
for (MCPResource resource : resources) {
if (resource.isValid()) {
resourcesBuilder.add(resource.toJsonObject());
}
}
JsonObject result = Json.createObjectBuilder()
.add("status", "success")
.add("count", resources.size())
.add("resources", resourcesBuilder.build())
.build();
return Response.ok(result).build();
} catch (Exception e) {
logger.severe("Error testing resources: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Json.createObjectBuilder()
.add("error", "Failed to parse resources")
.add("message", e.getMessage())
.build())
.build();
}
}
/**
* Quick test endpoint to list all available tools URL: /mcp/test/tools
*/
@GET
@Path("/test/tools")
public Response testTools() {
try {
List<MCPTool> tools = mcpService.parseTools();
JsonArrayBuilder toolsBuilder = Json.createArrayBuilder();
for (MCPTool tool : tools) {
if (tool.isValid()) {
toolsBuilder.add(tool.toJsonObject());
}
}
JsonObject result = Json.createObjectBuilder()
.add("status", "success")
.add("count", tools.size())
.add("tools", toolsBuilder.build())
.build();
return Response.ok(result).build();
} catch (Exception e) {
logger.severe("Error testing tools: " + e.getMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Json.createObjectBuilder()
.add("error", "Failed to parse tools")
.add("message", e.getMessage())
.build())
.build();
}
}
/**
* Health check endpoint URL: /mcp/health
*/
@GET
@Path("/health")
public Response healthCheck() {
try {
List<MCPResource> resources = mcpService.parseResources();
List<MCPTool> tools = mcpService.parseTools();
JsonObject health = Json.createObjectBuilder()
.add("status", "healthy")
.add("timestamp", java.time.Instant.now().toString())
.add("server", "Dynamixs.AI MCP Server")
.add("version", "1.0.0")
.add("protocol", "MCP 2024-11-05")
.add("endpoint", getBaseUrl() + "mcp/v1")
.add("resources_count", resources.size())
.add("tools_count", tools.size())
.build();
return Response.ok(health).build();
} catch (Exception e) {
logger.severe("Health check failed: " + e.getMessage());
return Response.status(Response.Status.SERVICE_UNAVAILABLE)
.entity(Json.createObjectBuilder()
.add("status", "unhealthy")
.add("error", e.getMessage())
.build())
.build();
}
}
/**
* Builds comprehensive server information (MCP equivalent of A2A Agent Card)
*/
private JsonObject buildServerInfo() {
List<MCPResource> resources = mcpService.parseResources();
List<MCPTool> tools = mcpService.parseTools();
// Server capabilities
JsonObject capabilities = Json.createObjectBuilder()
.add("resources", Json.createObjectBuilder()
.add("subscribe", false)
.add("listChanged", false)
.build())
.add("tools", Json.createObjectBuilder().build())
.add("logging", Json.createObjectBuilder().build())
.build();
// Protocol information
JsonObject protocol = Json.createObjectBuilder()
.add("name", "Model Context Protocol")
.add("version", "2024-11-05")
.add("transport", "HTTP/JSON-RPC 2.0")
.build();
// Server metadata
JsonObject server = Json.createObjectBuilder()
.add("name", "Dynamixs.AI MCP Server")
.add("version", "1.0.0")
.add("description", "MCP server for Imixs-Workflow BPM platform")
.add("vendor", "Dynamixs.AI")
.add("platform", "Jakarta EE 10 / Imixs-Workflow")
.build();
// Endpoints
JsonObject endpoints = Json.createObjectBuilder()
.add("jsonrpc", getBaseUrl() + "mcp/v1")
.add("health", getBaseUrl() + "mcp/health")
.add("server_info", getBaseUrl() + "mcp/server-info")
.add("test_resources", getBaseUrl() + "mcp/test/resources")
.add("test_tools", getBaseUrl() + "mcp/test/tools")
.build();
// Statistics
JsonObject statistics = Json.createObjectBuilder()
.add("resources_available", resources.size())
.add("tools_available", tools.size())
.add("last_updated", java.time.Instant.now().toString())
.build();
// Resource summary
JsonArrayBuilder resourceSummary = Json.createArrayBuilder();
for (MCPResource resource : resources) {
if (resource.isValid()) {
resourceSummary.add(Json.createObjectBuilder()
.add("uri", resource.getUri())
.add("name", resource.getName())
.add("mimeType", resource.getMimeType() != null ? resource.getMimeType() : "text/plain")
.build());
}
}
// Tool summary
JsonArrayBuilder toolSummary = Json.createArrayBuilder();
for (MCPTool tool : tools) {
if (tool.isValid()) {
toolSummary.add(Json.createObjectBuilder()
.add("name", tool.getName())
.add("description", tool.getDescription())
.build());
}
}
// Build complete server info
return Json.createObjectBuilder()
.add("protocol", protocol)
.add("server", server)
.add("capabilities", capabilities)
.add("endpoints", endpoints)
.add("statistics", statistics)
.add("resource_summary", resourceSummary.build())
.add("tool_summary", toolSummary.build())
.build();
}
private String getBaseUrl() {
return uriInfo.getBaseUri().toString();
}
}

View file

@ -1,283 +0,0 @@
package ai.dynamixs.mcp;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
/**
* Represents an MCP Tool based on Imixs-Workflow BPMN models.
*
* MCP Tools represent functions that can be called by the MCP client. Each tool
* corresponds to a workflow task/event combination.
*/
public class MCPTool implements Serializable {
private static final long serialVersionUID = 1L;
// MCP Standard Fields
private String name; // Tool name/identifier
private String description; // Tool description
private JsonObject inputSchema; // JSON Schema for input parameters
// Imixs-specific fields
private String modelVersion;
private int taskId;
private int eventId;
private List<String> tags;
private List<String> examples;
// Constructors
public MCPTool() {
this.tags = new ArrayList<>();
this.examples = new ArrayList<>();
}
public MCPTool(String modelVersion, int taskId, int eventId) {
this();
this.modelVersion = modelVersion;
this.taskId = taskId;
this.eventId = eventId;
this.name = createToolName(modelVersion, taskId, eventId);
}
/**
* Creates a tool name from Imixs workflow components
*/
public static String createToolName(String modelVersion, int taskId, int eventId) {
if (modelVersion == null || modelVersion.trim().isEmpty()) {
throw new IllegalArgumentException("Model version cannot be null or empty");
}
return String.format("%s_%d_%d", modelVersion.replace("-", "_"), taskId, eventId);
}
/**
* Parses model version from tool name
*/
public String getModelVersionFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
return name.substring(0, name.lastIndexOf('_', name.lastIndexOf('_') - 1)).replace("_", "-");
}
/**
* Parses task ID from tool name
*/
public int getTaskIdFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
String[] parts = name.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
try {
return Integer.parseInt(parts[parts.length - 2]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid task ID in tool name: " + name, e);
}
}
/**
* Parses event ID from tool name
*/
public int getEventIdFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
String[] parts = name.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
try {
return Integer.parseInt(parts[parts.length - 1]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid event ID in tool name: " + name, e);
}
}
/**
* Creates a default input schema for workflow tools
*/
public JsonObject createDefaultInputSchema() {
return Json.createObjectBuilder()
.add("type", "object")
.add("properties", Json.createObjectBuilder()
.add("workitem", Json.createObjectBuilder()
.add("type", "object")
.add("description", "Workflow item data")
.add("properties", Json.createObjectBuilder()
.add("$modelversion", Json.createObjectBuilder()
.add("type", "string")
.add("description", "Workflow model version")
.build())
.add("$taskid", Json.createObjectBuilder()
.add("type", "integer")
.add("description", "Task ID")
.build())
.add("$eventid", Json.createObjectBuilder()
.add("type", "integer")
.add("description", "Event ID")
.build())
.build())
.add("required", Json.createArrayBuilder()
.add("$modelversion")
.add("$taskid")
.add("$eventid")
.build())
.build())
.build())
.add("required", Json.createArrayBuilder()
.add("workitem")
.build())
.build();
}
/**
* Converts this tool to MCP JSON format
*/
public JsonObject toJsonObject() {
JsonObjectBuilder builder = Json.createObjectBuilder()
.add("name", name != null ? name : "")
.add("description", description != null ? description : "");
// Input schema
if (inputSchema != null) {
builder.add("inputSchema", inputSchema);
} else {
builder.add("inputSchema", createDefaultInputSchema());
}
return builder.build();
}
/**
* Creates an MCPTool from a JsonObject
*/
public static MCPTool fromJsonObject(JsonObject jsonObject) {
MCPTool tool = new MCPTool();
tool.setName(jsonObject.getString("name", ""));
tool.setDescription(jsonObject.getString("description", ""));
if (jsonObject.containsKey("inputSchema")) {
tool.setInputSchema(jsonObject.getJsonObject("inputSchema"));
}
return tool;
}
/**
* Validates this tool for MCP compliance
*/
public boolean isValid() {
if (name == null || name.trim().isEmpty()) {
return false;
}
if (description == null || description.trim().isEmpty()) {
return false;
}
// Validate tool name format
try {
getModelVersionFromName();
getTaskIdFromName();
getEventIdFromName();
} catch (Exception e) {
return false;
}
return true;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public JsonObject getInputSchema() {
return inputSchema;
}
public void setInputSchema(JsonObject inputSchema) {
this.inputSchema = inputSchema;
}
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public int getTaskId() {
return taskId;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags != null ? tags : new ArrayList<>();
}
public List<String> getExamples() {
return examples;
}
public void setExamples(List<String> examples) {
this.examples = examples != null ? examples : new ArrayList<>();
}
@Override
public String toString() {
return String.format("MCPTool{name='%s', description='%s', modelVersion='%s', taskId=%d, eventId=%d}",
name, description, modelVersion, taskId, eventId);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
MCPTool that = (MCPTool) obj;
return name != null ? name.equals(that.name) : that.name == null;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}

View file

@ -1,30 +0,0 @@
Imixs-Office-Workflow
Copyright (C) 2001-2018 Imixs Software Solutions GmbH,
http://www.imixs.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Project:
http://www.imixs.org
Contributors:
Imixs Software Solutions GmbH - initial API and implementation
Ralph Soika - Software Developer

View file

@ -1,621 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
bean-discovery-mode="all" version="3.0">
</beans>

View file

@ -1,10 +0,0 @@
Imixs Workflow Technology
Copyright (C) 2010 Imixs Software Solutions GmbH,
http://www.imixs.com
Contributors:
Imixs Software Solutions GmbH - initial implementation
Ralph Soika