clean project
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 });
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
??
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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(" ", " ")
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace(""", "\"")
|
||||
.replace("'", "'")
|
||||
.replace("ä", "ä").replace("Ä", "Ä")
|
||||
.replace("ö", "ö").replace("Ö", "Ö")
|
||||
.replace("ü", "ü").replace("Ü", "Ü")
|
||||
.replace("ß", "ß")
|
||||
.replace("é", "é").replace("É", "É")
|
||||
.replace("è", "è").replace("È", "È")
|
||||
.replace("ê", "ê").replace("Ê", "Ê")
|
||||
.replace("à", "à").replace("À", "À")
|
||||
.replace("â", "â").replace("Â", "Â")
|
||||
.replace("ô", "ô").replace("Ô", "Ô")
|
||||
.replace("û", "û").replace("Û", "Û")
|
||||
.replace("ç", "ç").replace("Ç", "Ç")
|
||||
.replace("ñ", "ñ").replace("Ñ", "Ñ")
|
||||
.replace("©", "©")
|
||||
.replace("®", "®")
|
||||
.replace("™", "™")
|
||||
.replace("—", "—")
|
||||
.replace("–", "–")
|
||||
.replace("…", "…")
|
||||
.replace("«", "«").replace("»", "»")
|
||||
.replace("•", "•")
|
||||
.replace("€", "€");
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Manifest-Version: 1.0
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -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}
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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');
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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&key=#{qrprafix}#{workflowController.workitem.uniqueID}">
|
||||
</h:graphicImage>
|
||||
</a>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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).
|
||||
|
|
@ -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 & 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 & 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>
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
Before Width: | Height: | Size: 62 KiB |
|
|
@ -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 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 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 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 200 65) translate(200 65 )"/>
|
||||
<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 450 65) translate(450 65 )"/>
|
||||
<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 657 65) translate(657 65 )"/>
|
||||
<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 |
|
|
@ -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 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 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 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 200 65) translate(200 65 )"/>
|
||||
<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 450 65) translate(450 65 )"/>
|
||||
<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 657 65) translate(657 65 )"/>
|
||||
<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 |
|
|
@ -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -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=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 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 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 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 200 65) translate(200 65 )"/>
|
||||
<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 450 65) translate(450 65 )"/>
|
||||
<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 657 65) translate(657 65 )"/>
|
||||
<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 |
|
|
@ -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 →</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 →</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 →</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 →</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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
??
|
||||