/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* 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 should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.web;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.onecmdb.core.ICcb;
import org.onecmdb.core.ICi;
import org.onecmdb.core.ICiModifiable;
import org.onecmdb.core.ICmdbTransaction;
import org.onecmdb.core.IModelService;
import org.onecmdb.core.IRfcResult;
import org.onecmdb.core.ISession;
import org.onecmdb.core.ITicket;
import org.springframework.validation.BindException;
public class AddCiAction extends EditCiAction implements FormAction {
private final Map<ICi, CountDown> countdownMap =
Collections.synchronizedMap( new HashMap<ICi, CountDown>(0) );
public AddCiAction() {
super("addci");
setDisplayName("Add");
}
private class CountDown extends Thread {
CountDown() {
countdownMap.put(getCi(), this);
setName(getCi().getId().toString());
start();
}
private boolean applied = false;
synchronized void setApplied(boolean b) {
this.applied = b;
notify();
}
public synchronized void run() {
if (!applied) {
try {
wait(60000);
} catch (InterruptedException e) { }
}
if (!applied) {
// remove the CI
System.out.println("Timeout!!!");
ISession session = getCommand().getSession();
IModelService model = (IModelService) session.getService(IModelService.class);
ICcb ccb = (ICcb) session.getService(ICcb.class);
ICmdbTransaction tx = ccb.getTx(session);
{
ICiModifiable tpl = tx.getTemplate(getCi());
tpl.delete();
}
ITicket ticket = ccb.submitTx(tx);
IRfcResult result = ccb.waitForTx(ticket);
if (result.isRejected()) {
System.out.println("Failed to delete timed out CI!");
}
}
countdownMap.remove(getCi());
}
};
@Override
protected void handleNavigationalChange(BindException errors) {
// we came here by a triggering to this action
// a new template object is needed
ICi ci = getCi();
final ICi newCi = createOffspring(getCi(), errors);
setCi(newCi);
if (errors.hasErrors()) {
cancel(errors);
return;
}
super.handleNavigationalChange(errors);
}
public void apply(BindException errors) {
super.apply(errors);
}
public void cancel(BindException errors) {
ICi newCi = this.getCi();
if (newCi != null) {
deleteOffspring(newCi, errors);
this.setCi((ICi) null);
}
SiteAction action = setReturnAction();
String returnParam = getReturnParam();
if (returnParam != null) {
action.getFormParams().revert(returnParam);
}
}
private SiteAction setReturnAction() {
String returnTo = getReturnTo();
if (returnTo!= null) {
getCommand().setNavigate(returnTo);
}
return getCommand().getAction();
}
protected void forward() {
SiteAction action = setReturnAction();
if (action == null) {
getCommand().setAction("viewci");
}
String returnParam = getReturnParam();
if (returnParam != null) {
ICi newCi = getCi();
action.getFormParams().put(returnParam, newCi);
}
}
private void deleteOffspring(ICi ci, BindException errors) {
ISession session = getCommand().getSession();
ICcb ccb = (ICcb) session.getService(ICcb.class);
ICmdbTransaction tx = ccb.getTx(session);
{
ICiModifiable tpl = tx.getTemplate(ci);
tpl.delete();
}
ITicket ticket = ccb.submitTx(tx);
IRfcResult result = ccb.waitForTx(ticket);
if (result.isRejected()) {
errors.reject("REJECT", new String[] {result.getRejectCause()}, result.getRejectCause());
}
}
private ICi createOffspring(ICi ci, BindException errors) {
Set<ICi> beforeSet = ci.getOffsprings();
ISession session = getCommand().getSession();
ICcb ccb = (ICcb) session.getService(ICcb.class);
ICmdbTransaction tx = ccb.getTx(session);
{
ICiModifiable tpl = tx.getTemplate(ci);
ICiModifiable offsping = tpl.createOffspring();
offsping.setIsBlueprint(false);
}
ITicket ticket = ccb.submitTx(tx);
IRfcResult result = ccb.waitForTx(ticket);
if (result.isRejected()) {
errors.reject("REJECT", new String[] {result.getRejectCause()}, result.getRejectCause());
return null;
}
/*
* removing the ones available before, leaves the newly created
* CI left as single element
*/
Set<ICi> newSet = ci.getOffsprings();
newSet.removeAll(beforeSet);
if (newSet.isEmpty()) {
errors.reject("ADDCI", new String[] {}, "Failed to create offspring");
return null;
} else {
return newSet.iterator().next();
}
}
}