<process>
	<!-- Main Process-->
	<context>
		<!-- Define the global variables.  The definition of properties is flexible. -->
		<property name="TryPayment"/>
		<property name="RetryCount">
			<value>0</value>
		</property>
		<property name="Approved">
			<value>true</value>
		</property>
		<property name="PaymentOK">
			<value>true</value>
		</property>
		<property name="NumberOfAirlines">
			<value>5</value>
		</property>
		<property name="NumberOfHotels">
			<value>6</value>
		</property>
		<!-- The main control flow -->
		<sequence>
			<action portType="tns:customerPort" operation="receiveOrder" name="Receive Order"/>
			<action portType="tns:bankPort" operation="sendreceiveVerification" name="Verify Payment Type is OK">
				<output select="Approved=True | False"/>
			</action>
			<sequence>
				<!-- documentation>
				This sequence is use for creating the context that will have the timeout and the message exception.  
				The perimeter of the sequence will be used and the Exception Events will be attached to that perimeter. 
				</documetation -->
				<switch name="Approved?">
					<case condition="Approved=False" name="No">
						<switch name="Type of Customer?">
							<case condition="xxxx" name="Established with Good Credit">
								<action portType="tns:internalPort" operation="sendReceiveApologyText" name="Include Text Apology"/>
								<call ref="SP - Include History of Transactions"/>
							</case>
							<case condition="xxxx" name="Established with Poor Credit">
								<call ref="SP - Include History of Transactions"/>
							</case>
							<default>
								<empty/>
							</default>
						</switch>
						<action portType="tns:customerPort" operation="sendRejection" name="Send Order Status"/>
					</case>
					<default name="Yes">
						<!-- Valid Order -->
						<all>
							<sequence>
								<!-- documentation>
								A parallel multi-instace object will be created by spawning multiple copies of a sub-process with 
								a foreach.  A Join the synchronizes the sub-processes.  A sequence will be created to support it.
								For a sequential multi-instance object a call will be used instead of a spawn/join, and a sequence will
								not be necessary.
								</documetation -->
								<foreach select="range(1,NumberOfAirlines)">
									<spawn ref="SP - Request Flights with Parameters"/>
								</foreach>
								<join ref="SP - Request Flights with Parameters"/>
							</sequence>
							<sequence>
								<foreach select="range(1,NumberOfHotels)">
									<spawn ref="SP - Request Rooms with Parameters"/>
								</foreach>
								<join ref="SP - Request Rooms with Parameters"/>
							</sequence>
						</all>
						<!--The call below will be shown as a sub-process object -->
						<call ref="prepare and Send Candidate Itineraries"/>
						<sequence perimeter="false">
							<!-- documentation>
							This sequence is use for creating the context that will have the timeout.  
							The perimeter of the sequence will not be used and the Exception Event will be attached to the Activity. 
							</documetation -->
							<action portType="tns:customerPort" operation="receiveConfirmation" name="Receive Confirmation"/>
							<context perimeter="true">
								<exception>
									<onTimeout type="duration:2 days">
										<action portType="tns:customerPort" operation="sendCancellation" name="Send Cancellation Notice"/>
										<fault code="Stop Process"/>
										<!-- The fault will cause the higher-level sequence to abort -->
									</onTimeout>
								</exception>
							</context>
						</sequence>
						<all>
							<!-- This all will be a transaction and thus will have a double border -->
							<action portType="tns:airlinePort" operation="sendFlightReservation" name="Book Flight"/>
							<action portType="tns:hotelPort" operation="sendHotelReservation" name="Book Hotel"/>
							<context perimeter="true">
								<transaction name="Unbook" type="open">
									<compensation>
										<all>
											<action portType="tns:customerPort" operation="sendCancellation" name="Send Cancellation Notice"/>
											<action portType="tns:airlinePort" operation="sendFlightCancellation" name="Send Flight Cancellation"/>
											<action portType="tns:hotelPort" operation="sendHotelCancellation" name="Send Hotel Cancellation"/>
										</all>
									</compensation>
								</transaction>
							</context>
						</all>
						<until condition="RetryCount=3" name="until payment ok">
							<assign property="tryPayment" select="false" name="Retry = False"/>
							<sequence perimeter="false">
								<!-- This sequence is set up to handle the transaction -->
								<action portType="tns:bankPort" operation="sendCharge" name="Charge Buyer">
									<output select="PaymentOK=True | False"/>
								</action>
								<context perimeter="true">
									<transaction name="Refund" type="open">
										<compensation>
											<action portType="tns:bankPort" operation="sendRefund" name="Credit Customer"/>
										</compensation>
									</transaction>
								</context>
							</sequence>
							<switch name="payment ok?">
								<case condition="PaymentOK=false" name="No">
									<action name="Send Payment Problem"/>
									<sequence>
										<!-- This sequence is set up to handle the time out -->
										<choice>
											<onMessage>
												<action portType="tns:customerPort" operation="receiveUpdate" name="Receive Update"/>
												<assign property="tryPayment" select="true" name="Retry = True"/>
												<assign property="RetryCount" select="RetryCount+1" name="RetryCount+1"/>
											</onMessage>
											<onMessage>
												<action portType="tns:customerPort" operation="receiveCancel" name="Receive Cancel"/>
												<compensate name="Unbook"/>
											</onMessage>
										</choice>
										<context perimeter="true">
											<exception>
												<onTimeout type="duration:2 days">
													<call ref="Contact Customer"/>
												</onTimeout>
											</exception>
										</context>
									</sequence>
								</case>
								<case condition="(PaymentOK=false) and (RetryCount>3)" name="No, Exceeded Retry Limit">
									<compensate code="Unbook"/>
								</case>
								<default name="Yes">
									<action portType="tns:customerPort" operation="sendConfirmation" name="Send Confirmation"/>
								</default>
							</switch>
						</until>
					</default>
				</switch>
				<context>
					<!-- documentation>
						This is the context for the hidden sequence.
						</documetation -->
					<exception>
						<onFault code="Stop Process">
							<empty/>
						</onFault>
						<onMessage code="Cancel Received">
							<spawn ref="Handle Cancel Message"/>
						</onMessage>
					</exception>
				</context>
			</sequence>
		</sequence>
		<!-- the main flow is done -->
		<process name="SP - Include History of Transactions">
			<action portType="tns:internalPort" operation="sendReceiveCustomerHistory" name="Include History of Transactions"/>
		</process>
		<process name="SP - Request Flights with Parameters">
			<action portType="tns:airlinePort" operation="sendFlightRequest" name="Request Flights with Parameters"/>
		</process>
		<process name="SP - Request Rooms with Parameters">
			<action portType="tns:hotelPort" operation="sendHotelRequest" name="Request Rooms with Parameters"/>
		</process>
		<process name="Prepare and Send Candidate Itineraries">
			<!-- documentation>
				This is the nested process that is called.
			</documetation -->
			<action portType="tns:internalPort" operation="sendreceiveList" name="Organize List of Itineraries">
				<locate locator="Sorting Application"/>
			</action>
			<action portType="tns:customerPort" operation="sendList" name="Send Itineraries"/>
		</process>
		<process name="Contact Customer">
			<context>
				<!-- This is a nested process that is called.  Some local variables are defined. -->
				<property name="CallCount">
					<value>0</value>
				</property>
				<property name="CallCompleted">
					<value>false</value>
				</property>
				<property name="CallSuccessful">
					<value>false</value>
				</property>
				<sequence>
					<until condition="(CallCompleted=true) or (CallCount>3)" name="No Answer, Less than 4 tries">
						<assign property="CallCompleted" select="false" name="Competed = False"/>
						<assign property="CallCount" select="CallCount+1" name="CallCount + 1"/>
						<action portType="tns:internalPort" operation="sendreceiveCallInformation" name="Phone Customer">
							<locate locator="Workflow Manager"/>
							<!-- The message to the Workflow Manager should include the Role "Travel Agent" and a path to 
							any client that the User will need -->
							<output select="CallCompleted=True | False"/>
							<output select="CallSuccessful=True | False"/>
						</action>
						<switch name="Result of Phonecall?">
							<case condition="CallSuccessful=true" name="Update">
								<documentation>
									This updates the TryPayment Variable which is used in the until named
									"updated -- try again" in the main process.  The timeout which lead
									here is inside the until and thus, does not about the until.
								</documentation>
								<assign property="TryPayment" select="true" name="Retry = True"/>
							</case>
							<case condition="(CallCompleted=false) and (CallCount>3)" name="Cancel, After 3 Tries">
								<compensate code="Unbook"/>
							</case>
							<default name="No Answer">
								<delay type="duration:1 day" name="1 Day"/>
							</default>
						</switch>
					</until>
				</sequence>
			</context>
		</process>
		<process name="Handle Cancel Message">
			<!-- documentation>
				This is the nested process that is called.
			</documetation -->
			<switch name="Any Compensation?">
				<case condition="Send Confirmation.status=complete" name="Yes">
					<compensate name="Unbook"/>
					<compensate name="Refund"/>
				</case>
				<case condition="(Book Flight.status=complete) and (Book Hotel.status=complete)" name="Everything">
					<compensate name="Unbook"/>
				</case>
				<default name="None">
					<empty/>
					<!-- nothing left to be done -->
				</default>
			</switch>
		</process>
	</context>
</process>
