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 java.util.ArrayList;
020 import java.util.List;
021
022 import org.apache.camel.Endpoint;
023 import org.apache.camel.Processor;
024 import org.apache.camel.Route;
025 import org.apache.camel.bam.model.ActivityDefinition;
026 import org.apache.camel.bam.model.ProcessDefinition;
027 import org.apache.camel.bam.model.ProcessInstance;
028 import org.apache.camel.bam.processor.ActivityMonitorEngine;
029 import org.apache.camel.bam.processor.JpaBamProcessor;
030 import org.apache.camel.bam.rules.ProcessRules;
031 import org.apache.camel.builder.RouteBuilder;
032
033 import org.springframework.orm.jpa.JpaTemplate;
034 import org.springframework.transaction.TransactionStatus;
035 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
036 import org.springframework.transaction.support.TransactionTemplate;
037
038 import static org.apache.camel.util.ObjectHelper.notNull;
039
040 /**
041 * A builder of a process definition
042 *
043 * @version $Revision: $
044 */
045 public abstract class ProcessBuilder extends RouteBuilder {
046 private static int processCounter;
047 private JpaTemplate jpaTemplate;
048 private final TransactionTemplate transactionTemplate;
049 private final String processName;
050 private List<ActivityBuilder> activityBuilders = new ArrayList<ActivityBuilder>();
051 private Class entityType = ProcessInstance.class;
052 private ProcessRules processRules = new ProcessRules();
053 private ProcessDefinition processDefinition;
054
055 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate) {
056 this(jpaTemplate, transactionTemplate, createProcessName());
057 }
058
059 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate, String processName) {
060 this.jpaTemplate = jpaTemplate;
061 this.transactionTemplate = transactionTemplate;
062 this.processName = processName;
063 }
064
065 protected static synchronized String createProcessName() {
066 return "Process-" + (++processCounter);
067 }
068
069 public ActivityBuilder activity(String endpointUri) {
070 return activity(endpoint(endpointUri));
071 }
072
073 public ActivityBuilder activity(Endpoint endpoint) {
074 ActivityBuilder answer = new ActivityBuilder(this, endpoint);
075 activityBuilders.add(answer);
076 return answer;
077 }
078
079 /**
080 * Sets the process entity type used to perform state management
081 */
082 public ProcessBuilder entityType(Class entityType) {
083 this.entityType = entityType;
084 return this;
085 }
086
087 public Processor createActivityProcessor(ActivityBuilder activityBuilder) {
088 notNull(jpaTemplate, "jpaTemplate");
089 transactionTemplate.execute(new TransactionCallbackWithoutResult() {
090 protected void doInTransactionWithoutResult(TransactionStatus status) {
091 processRules.setProcessDefinition(getProcessDefinition());
092 }
093 });
094 return new JpaBamProcessor(getTransactionTemplate(), getJpaTemplate(), activityBuilder.getCorrelationExpression(), activityBuilder.getActivityRules(), getEntityType());
095 }
096
097 // Properties
098 // -----------------------------------------------------------------------
099 public List<ActivityBuilder> getActivityBuilders() {
100 return activityBuilders;
101 }
102
103 public Class getEntityType() {
104 return entityType;
105 }
106
107 public JpaTemplate getJpaTemplate() {
108 return jpaTemplate;
109 }
110
111 public void setJpaTemplate(JpaTemplate jpaTemplate) {
112 this.jpaTemplate = jpaTemplate;
113 }
114
115 public TransactionTemplate getTransactionTemplate() {
116 return transactionTemplate;
117 }
118
119 public ProcessRules getProcessRules() {
120 return processRules;
121 }
122
123 public String getProcessName() {
124 return processName;
125 }
126
127 public ProcessDefinition getProcessDefinition() {
128 if (processDefinition == null) {
129 processDefinition = findOrCreateProcessDefinition();
130 }
131 return processDefinition;
132 }
133
134 public void setProcessDefinition(ProcessDefinition processDefinition) {
135 this.processDefinition = processDefinition;
136 }
137
138 // Implementation methods
139 // -------------------------------------------------------------------------
140 protected void populateRoutes(List<Route> routes) throws Exception {
141 boolean first = true;
142 for (ActivityBuilder builder : activityBuilders) {
143 Route route = builder.createRoute();
144 if (first) {
145 route.getServices().add(new ActivityMonitorEngine(getJpaTemplate(), getTransactionTemplate(), getProcessRules()));
146 first = false;
147 }
148 routes.add(route);
149 }
150 }
151
152 // Implementation methods
153 // -------------------------------------------------------------------------
154 public ActivityDefinition findOrCreateActivityDefinition(String activityName) {
155 ProcessDefinition definition = getProcessDefinition();
156 List<ActivityDefinition> list = jpaTemplate.find("select x from " + ActivityDefinition.class.getName() + " x where x.processDefinition = ?1 and x.name = ?2", definition, activityName);
157 if (!list.isEmpty()) {
158 return list.get(0);
159 } else {
160 ActivityDefinition answer = new ActivityDefinition();
161 answer.setName(activityName);
162 answer.setProcessDefinition(ProcessDefinition.getRefreshedProcessDefinition(jpaTemplate, definition));
163 jpaTemplate.persist(answer);
164 return answer;
165 }
166 }
167
168 protected ProcessDefinition findOrCreateProcessDefinition() {
169 List<ProcessDefinition> list = jpaTemplate.find("select x from " + ProcessDefinition.class.getName() + " x where x.name = ?1", processName);
170 if (!list.isEmpty()) {
171 return list.get(0);
172 } else {
173 ProcessDefinition answer = new ProcessDefinition();
174 answer.setName(processName);
175 jpaTemplate.persist(answer);
176 return answer;
177 }
178 }
179 }