/* * 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.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.onecmdb.core.IAttribute; import org.onecmdb.core.ICi; import org.onecmdb.core.IJobService; import org.onecmdb.core.IModelService; import org.onecmdb.core.IPath; import org.onecmdb.core.IReferenceService; import org.onecmdb.core.IService; import org.onecmdb.core.ISession; import org.onecmdb.core.IType; import org.onecmdb.core.internal.model.ItemId; import org.onecmdb.core.internal.model.Path; /** * * Every new _session in the web application will be given a new instance of * this class, and is responsible to keep track of the user's _session data.</p> * * <p><b>Note:</b> Even though the web application is deployed as a servlet * application, the servlet _session mechanism is hidden by the use of this * class.</p> * * The command object represented by this class, site, and updated via * submissions from the view. * * <p>Each _session will have a single instance of this object, and will * operate as a session state object.</p> */ public class SiteCommand { private SiteAction _previous; private SiteAction _action; private ISession _session; private SiteAction _rootAction; private String mode = "design"; private final List<SiteAction> _history = new ArrayList<SiteAction>(); /** all actions recognized. The values should be considered templates, which * are cloned when the user <em>enters</em> a actions. */ private final Map<String,SiteAction> _actionMap = new HashMap<String,SiteAction>(); private boolean debug = false; private String _navigate; /** the controller <em>in charge</em> */ private SiteController _controller; public class MemoryObject { private ItemId _id; volatile private ICi _ci; public void setId(ItemId id) { _id = id; _ci = null; } public void setCi(ICi ci) { setId(ci.getId()); _ci = ci; } public ItemId getId() { return _id; } public ICi getCi() { if (_ci == null && _id != null) { IModelService modelsvc = (IModelService) getSession().getService(IModelService.class); setCi(modelsvc.find(_id)); } return _ci; } } /** default no-arg constructor */ public SiteCommand() { super(); } public void setDebugEnabled(boolean b) { this.debug = b; } public boolean isDebugEnabled() { return this.debug; } /** Recursively adds all actions passed in */ private void addAction(final SiteAction action) { if ( !_actionMap.containsKey(action.getName()) ) { _actionMap.put(action.getName(), action); } for (SiteAction subaction : action.getSubActionMap().values()) { if ( !_actionMap.containsKey(subaction.getName()) ) { addAction(subaction); } } } public final String getVersion() { return "CORE v" + org.onecmdb.core.Version.getVersionString() + "; GUI v" + org.onecmdb.web.Version.getVersionString(); } public final long getCurrenttimeMillis() { return System.currentTimeMillis(); } private void setSession(ISession session) { if (_session == null) _session = session; else { throw new IllegalStateException("Already have a session"); } } public void setRootAction(SiteAction action) { _rootAction = action; } public SiteAction getRootAction() { return _rootAction; } public ISession getSession() { return _session; } /** * Set the action to use, using the name to look up the actual one. When * found (in the action map) it is cloned, to make sure * the user is given an action holding no previous state. * @param actionName The name of the action to use * @throws IllegalArgumentException in case the action with the name can * not be found. */ public void setAction(String actionName) { SiteAction actionTemplate = _actionMap.get(actionName); if (actionTemplate == null) { throw new IllegalArgumentException("Unknown action: " + actionName); } SiteAction newAction = (SiteAction) actionTemplate.clone(); setAction(newAction); } private void setAction(SiteAction newAction) { updatePrevious(); _action = newAction; } /** current _action */ public SiteAction getAction() { return _action; } /** the previously used _action */ public void updatePrevious() { if (_action != null && !_action.equals(_previous) ) { _previous = (SiteAction) _action; } } public SiteAction getPrevious() { return _previous; } /** * All actions defined for this command, i.e. session, considered * templates. */ public Map<String,SiteAction> getActionMap() { return _actionMap; } /** make sure we update the _history */ public final void setSubmit(String submit) { setAction(getAction()); } SiteAction getHistory(String hash) { SiteAction history = null; if (hash.startsWith("#")) { String number = hash.substring(1); int abs = Integer.parseInt(number); history = getHistory().get(abs); } return history; } /** * <p>Set the navigational information for a request, indicating the * <em>view</em> to process.</p> * * @param navigate A string representing the navigational operation; can * indicate a history item using one of * <ol> * <li>an actual number (<code>#nnn</code>) * <li>a relative number (<code>+/-nnn</code>) * </ol> * or a a name of an existing action. */ public void setNavigate(String navigate) { navigate = navigate.split(",")[0]; _navigate = navigate; final SiteAction action; if (navigate.startsWith("#")) { // _navigate to specific history item String number = navigate.substring(1); int abs = Integer.parseInt(number); action = getHistory().get(abs); int i = abs + 1; while (getHistory().size() > i) { getHistory().remove(i); } } else if (navigate.startsWith("-") || navigate.startsWith("+")) { // _navigate relative current _action (_history not altered) String number = navigate; int rel = Integer.parseInt(number); int abs = 0; for (SiteAction history : getHistory()) { if (history.equals(getAction())) { break; } abs++; } action = getHistory().get(abs + rel); } else if (!"".equals(navigate)) { action = (SiteAction) getActionMap().get(navigate).clone(); } else { action = getAction(); } setAction(action); } public String getNavigate() { return _navigate; } // {{{ handle the navigation _history /** * indicates whether a navigational change has occurred. */ public boolean isNavigationalChange() { return !getAction().equals(getPrevious()); } public int getHistoryLength() { return _history.size(); } public String getCurrentHistory() { final SiteAction current = getAction(); int index = 0; for (SiteAction action : getHistory()) { if (action.equals(current)) { return "#" + index; } index++; } return "#0"; } public void setHistory(SiteAction action) { _history.clear(); addHistory(action); } public void setHistory(List<SiteAction> actions) { _history.clear(); for (SiteAction action : actions) { addHistory(action); } } public List<SiteAction> getHistory() { return _history; } public void addHistory(SiteAction action) { if (action.equals(getPrevious())) { return; } int last = _history.size(); if (last > 0) { SiteAction lastAction = _history.get(last - 1); if (action.equals(lastAction)) { return; } } // the _history keeps a clone of the actual _action //SiteAction copy = (SiteAction) action.clone(); _history.add(action); /* if (!this.history.contains(copy)) { if (!this.history.isEmpty()) { SiteAction lastAction = this.history.get(this.history.size() -1); if (!lastAction.equals(copy)) { this.history.add(copy); } } else { this.history.add(copy); } } */ } // }}} public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public Set<IType> getAllTypes() { IModelService model = (IModelService) getSession().getService(IModelService.class); IPath<String> base = getController().getTemplateBase(); Set<IType> types = model.getAllBuiltInTypes(); types.addAll(model.getAllComplexTypes(base)); return types; } public Set<IType> getSimpleTypes() { IModelService model = (IModelService) getSession().getService(IModelService.class); Set<IType> types = model.getAllBuiltInTypes(); return types; } /** * Return all types, keyed according to the implementation used; either * <em>complex</em>, or <em>simple</em> * @return */ public Map<String, Set<IType>> getTypeMap() { final Comparator<IType> comparator = new Comparator<IType>() { public int compare(IType o1, IType o2) { return o1.getDisplayName().compareTo(o2.getDisplayName()); }}; TreeMap<String, Set<IType>> typeMap = new TreeMap<String, Set<IType>>(); IModelService model = (IModelService) getSession().getService(IModelService.class); Set<IType> builtinTypes = model.getAllBuiltInTypes(); for (IType type : builtinTypes) { // simple Set<IType> types ; String typeName="Built-In"; types = typeMap.get(typeName); if (types == null) { types = new TreeSet<IType>(comparator); typeMap.put(typeName, types); } types.add(type); } IPath<String> base = getController().getTemplateBase(); Set<IType> complexTypes = model.getAllComplexTypes(base); for (IType type : complexTypes) { // complex Set<IType> types ; String typeName="User Defined"; types = typeMap.get(typeName); if (types == null) { types = new TreeSet<IType>(comparator); typeMap.put(typeName, types); } types.add(type); } return typeMap; } public Set<IType> getAllRefTypes() { IReferenceService refsvc = (IReferenceService) getSession().getService(IReferenceService.class); IPath<String> base = getController().getRefsBase(); Set<IType> refs = refsvc.getAllReferences(base); return refs; } public void setController(SiteController controller) { _controller = controller; } protected SiteController getController() { return _controller; } // {{{ simple global storage private final Map<String,Object> _globalData = new HashMap<String, Object>(); public Map<String,Object> getGlobals() { return _globalData; } // }}} void reset() { List<SiteAction> hist = getHistory(); while (hist.size() > 1) { hist.remove(1); } _globalData.put("graphData", new GraphCommand()); _globalData.put("showSearch", true); _globalData.put("showHistory", true); _globalData.put("showActions", false); _globalData.put("showTemplateChain", true); _globalData.put("showGraph", false); _globalData.put("showAttributes", true); _globalData.put("showReferences", true); // inititiate the MEM placeholder _globalData.put("mem", new MemoryObject()); setAction(getRootAction().getName()); } void init() { ISession newSession = getController().getOneCmdb().createSession(); setSession(newSession); if (!getActionMap().isEmpty()) { throw new IllegalStateException("Already initialized"); } // TODO: inject from outside SiteAction test = new SiteAction("test"); addAction(test); SiteAction denied = new SiteAction("denied"); denied.setDisplayName("Access Denied"); addAction(denied); SiteAction homeAction = new SiteAction("instructions"); homeAction.setDisplayName("Instructions"); SiteAction helpAction = new SiteAction("help"); helpAction.setDisplayName("Help"); homeAction.addSubAction(helpAction); SiteAction searchResultAction =new SearchResultAction(); addAction(searchResultAction); SiteAction addiconAction = new AddIconAction(); homeAction.addSubAction(addiconAction); ViewCiAction viewAction = new ViewCiAction(); addAction(viewAction); EditCiAction editAction = new EditCiAction(); addAction(editAction); AddCiAction addCiAction = new AddCiAction(); addAction(addCiAction); ViewChangeLogAction chlogAction = new ViewChangeLogAction(); addAction(chlogAction); viewAction.addSubAction(viewAction); viewAction.addSubAction(editAction); viewAction.addSubAction(chlogAction); editAction.addSubAction(viewAction); editAction.addSubAction(editAction); editAction.addSubAction(chlogAction); chlogAction.addSubAction(viewAction); chlogAction.addSubAction(editAction); chlogAction.addSubAction(chlogAction); //homeAction.addSubAction(viewAction); addAction(homeAction); setRootAction(homeAction); reset(); _globalData.put("__init", true); } public List<ICi> getJobs() { List<ICi> result = new ArrayList<ICi>(); IJobService jobsvc = (IJobService) getSession().getService(IJobService.class); ICi jobroot = jobsvc.getRootManualTrigger(); for (ICi trigger : jobroot.getOffsprings()) { List<IAttribute> procs = trigger.getAttributesWithAlias("process"); if (procs.size() == 1) { IAttribute proc = procs.get(0); if (!proc.isNullValue()) { ICi job = (ICi) proc.getValue(); result.add(job); } } } return result; } }