001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.bam;
018
019 import org.apache.camel.Endpoint;
020 import org.apache.camel.Processor;
021 import org.apache.camel.Route;
022 import org.apache.camel.bam.model.ActivityDefinition;
023 import org.apache.camel.bam.model.ProcessDefinition;
024 import org.apache.camel.bam.model.ProcessInstance;
025 import org.apache.camel.bam.processor.ActivityMonitorEngine;
026 import org.apache.camel.bam.processor.JpaBamProcessor;
027 import org.apache.camel.bam.rules.ProcessRules;
028 import org.apache.camel.builder.RouteBuilder;
029 import static org.apache.camel.util.ObjectHelper.notNull;
030 import org.springframework.orm.jpa.JpaTemplate;
031 import org.springframework.transaction.TransactionStatus;
032 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
033 import org.springframework.transaction.support.TransactionTemplate;
034
035 import java.util.ArrayList;
036 import java.util.List;
037
038 /**
039 * A builder of a process definition
040 *
041 * @version $Revision: $
042 */
043 public abstract class ProcessBuilder extends RouteBuilder {
044 private static int processCounter;
045 private JpaTemplate jpaTemplate;
046 private final TransactionTemplate transactionTemplate;
047 private final String processName;
048 private List<ActivityBuilder> activityBuilders = new ArrayList<ActivityBuilder>();
049 private Class entityType = ProcessInstance.class;
050 private ProcessRules processRules = new ProcessRules();
051 private ProcessDefinition processDefinition;
052
053 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate) {
054 this(jpaTemplate, transactionTemplate, createProcessName());
055 }
056
057 protected static synchronized String createProcessName() {
058 return "Process-" + (++processCounter);
059 }
060
061 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate, String processName) {
062 this.jpaTemplate = jpaTemplate;
063 this.transactionTemplate = transactionTemplate;
064 this.processName = processName;
065 }
066
067 public ActivityBuilder activity(String endpointUri) {
068 return activity(endpoint(endpointUri));
069 }
070
071 public ActivityBuilder activity(Endpoint endpoint) {
072 ActivityBuilder answer = new ActivityBuilder(this, endpoint);
073 activityBuilders.add(answer);
074 return answer;
075 }
076
077 /**
078 * Sets the process entity type used to perform state management
079 */
080 public ProcessBuilder entityType(Class entityType) {
081 this.entityType = entityType;
082 return this;
083 }
084
085 public Processor createActivityProcessor(ActivityBuilder activityBuilder) {
086 notNull(jpaTemplate, "jpaTemplate");
087 transactionTemplate.execute(new TransactionCallbackWithoutResult() {
088 protected void doInTransactionWithoutResult(TransactionStatus status) {
089 processRules.setProcessDefinition(getProcessDefinition());
090 }
091 });
092 return new JpaBamProcessor(getTransactionTemplate(), getJpaTemplate(), activityBuilder.getCorrelationExpression(), activityBuilder.getActivityRules(), getEntityType());
093 }
094
095 // Properties
096 //-----------------------------------------------------------------------
097 public List<ActivityBuilder> getActivityBuilders() {
098 return activityBuilders;
099 }
100
101 public Class getEntityType() {
102 return entityType;
103 }
104
105 public JpaTemplate getJpaTemplate() {
106 return jpaTemplate;
107 }
108
109 public void setJpaTemplate(JpaTemplate jpaTemplate) {
110 this.jpaTemplate = jpaTemplate;
111 }
112
113 public TransactionTemplate getTransactionTemplate() {
114 return transactionTemplate;
115 }
116
117 public ProcessRules getProcessRules() {
118 return processRules;
119 }
120
121 public String getProcessName() {
122 return processName;
123 }
124
125 public ProcessDefinition getProcessDefinition() {
126 if (processDefinition == null) {
127 processDefinition = findOrCreateProcessDefinition();
128 }
129 return processDefinition;
130 }
131
132 public void setProcessDefinition(ProcessDefinition processDefinition) {
133 this.processDefinition = processDefinition;
134 }
135
136 // Implementation methods
137 //-------------------------------------------------------------------------
138 protected void populateRoutes(List<Route> routes) throws Exception {
139 boolean first = true;
140 for (ActivityBuilder builder : activityBuilders) {
141 Route route = builder.createRoute();
142 if (first) {
143 route.getServices().add(new ActivityMonitorEngine(getJpaTemplate(), getTransactionTemplate(), getProcessRules()));
144 first = false;
145 }
146 routes.add(route);
147 }
148 }
149
150 // Implementation methods
151 //-------------------------------------------------------------------------
152 public ActivityDefinition findOrCreateActivityDefinition(String activityName) {
153 ProcessDefinition definition = getProcessDefinition();
154 List<ActivityDefinition> list = jpaTemplate.find("select x from " + ActivityDefinition.class.getName() + " x where x.processDefinition = ?1 and x.name = ?2", definition, activityName);
155 if (!list.isEmpty()) {
156 return list.get(0);
157 }
158 else {
159 ActivityDefinition answer = new ActivityDefinition();
160 answer.setName(activityName);
161 answer.setProcessDefinition(ProcessDefinition.getRefreshedProcessDefinition(jpaTemplate, definition));
162 jpaTemplate.persist(answer);
163 return answer;
164 }
165 }
166
167 protected ProcessDefinition findOrCreateProcessDefinition() {
168 List<ProcessDefinition> list = jpaTemplate.find("select x from " + ProcessDefinition.class.getName() + " x where x.name = ?1", processName);
169 if (!list.isEmpty()) {
170 return list.get(0);
171 }
172 else {
173 ProcessDefinition answer = new ProcessDefinition();
174 answer.setName(processName);
175 jpaTemplate.persist(answer);
176 return answer;
177 }
178 }
179 }