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 */
017package org.apache.isis.objectstore.jdo.applib.service.command;
018
019import java.util.UUID;
020
021import org.slf4j.Logger;
022import org.slf4j.LoggerFactory;
023
024import org.apache.isis.applib.AbstractService;
025import org.apache.isis.applib.annotation.Command.ExecuteIn;
026import org.apache.isis.applib.annotation.Command.Persistence;
027import org.apache.isis.applib.annotation.DomainService;
028import org.apache.isis.applib.annotation.Programmatic;
029import org.apache.isis.applib.clock.Clock;
030import org.apache.isis.applib.services.command.Command;
031import org.apache.isis.applib.services.command.Command.Executor;
032import org.apache.isis.applib.services.command.spi.CommandService;
033
034/**
035 *
036 */
037@DomainService
038public class CommandServiceJdo extends AbstractService implements CommandService {
039
040    @SuppressWarnings("unused")
041    private static final Logger LOG = LoggerFactory.getLogger(CommandServiceJdo.class);
042
043    /**
044     * Creates an {@link CommandJdo}, initializing its 
045     * {@link Command#setExecuteIn(Command.ExecuteIn) nature} to be
046     * {@link Command.ExecuteIn#OTHER rendering}.
047     */
048    @Programmatic
049    @Override
050    public Command create() {
051        CommandJdo command = newTransientInstance(CommandJdo.class);
052        command.setExecutor(Executor.OTHER);
053        command.setPersistence(Persistence.IF_HINTED);
054        return command;
055    }
056
057    @Programmatic
058    @Override
059    public void startTransaction(final Command command, final UUID transactionId) {
060        if(command instanceof CommandJdo) {
061            // should be the case, since this service created the object in the #create() method
062            final CommandJdo commandJdo = (CommandJdo) command;
063            final UUID currentTransactionId = commandJdo.getTransactionId();
064            if(currentTransactionId != null && !currentTransactionId.equals(transactionId)) {
065                // the logic in IsisTransaction means that any subsequent transactions within a given command
066                // should reuse the xactnId of the first transaction created within that interaction.
067                throw new IllegalStateException("Attempting to set a different transactionId on command");
068            }
069            commandJdo.setTransactionId(transactionId);
070        }
071    }
072
073    @Programmatic
074    @Override
075    public void complete(final Command command) {
076        final CommandJdo commandJdo = asUserInitiatedCommandJdo(command);
077        if(commandJdo == null) {
078            return;
079        }
080        if(commandJdo.getCompletedAt() != null) {
081            // already attempted to complete.
082            // chances are, we're here as the result of a redirect following a previous exception
083            // so just ignore.
084            return;
085        }
086            
087        commandJdo.setCompletedAt(Clock.getTimeAsJavaSqlTimestamp());
088        persistIfNotAlready(commandJdo);
089    }
090
091    @Override
092    public boolean persistIfPossible(Command command) {
093        if(!(command instanceof CommandJdo)) {
094            // ought not to be the case, since this service created the object in the #create() method
095            return false;
096        }
097        final CommandJdo commandJdo = (CommandJdo)command;
098        persistIfNotAlready(commandJdo);
099        return true;
100    }
101    
102    
103    /**
104     * Not API, also used by {@link CommandServiceJdoRepository}.
105     */
106    CommandJdo asUserInitiatedCommandJdo(final Command command) {
107        if(!(command instanceof CommandJdo)) {
108            // ought not to be the case, since this service created the object in the #create() method
109            return null;
110        }
111        if(command.getExecuteIn() != ExecuteIn.FOREGROUND) {
112            return null;
113        } 
114        final CommandJdo commandJdo = (CommandJdo) command;
115        return commandJdo.shouldPersist()? commandJdo: null;
116    }
117
118    
119}