001/*
002 * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.connect.update.task.standalone.commands;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.w3c.dom.Element;
023
024import org.nuxeo.connect.update.PackageException;
025import org.nuxeo.connect.update.ValidationStatus;
026import org.nuxeo.connect.update.task.Command;
027import org.nuxeo.connect.update.task.Task;
028import org.nuxeo.connect.update.task.guards.Guard;
029
030/**
031 * All commands have 2 attributes: fail and ignore which are EL expressions.
032 * <p>
033 * If ignore is defined and evaluated to true then the command will be ignored (null is returned as the inverse command)
034 * If fail is defined and evaluated to true then the validation fails.
035 * <p>
036 * Commands extending this class must implement the {@link #doRun} and {@link #doValidate} methods instead of the one in
037 * the interface. These methods are first testing for ignore and fail guards and then if needed delegated to the doXXX
038 * method versions.
039 *
040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
041 */
042public abstract class AbstractCommand implements Command {
043
044    /**
045     * List of files which must never be deleted at runtime.
046     *
047     * @since 5.5
048     */
049    protected final String id;
050
051    protected final Map<String, Object> guardVars;
052
053    protected String fail;
054
055    protected String ignore;
056
057    protected AbstractCommand(String id) {
058        this.id = id;
059        guardVars = new HashMap<>();
060    }
061
062    public AbstractCommand(AbstractCommand command) {
063        this.id = command.id;
064        guardVars = command.guardVars;
065    }
066
067    @Override
068    public boolean isPostInstall() {
069        return false;
070    }
071
072    /**
073     * Override to implement command actions
074     *
075     * @param task
076     * @param prefs
077     * @return Rollback command
078     * @throws PackageException
079     */
080    protected abstract Command doRun(Task task, Map<String, String> prefs) throws PackageException;
081
082    /**
083     * Override to implement validation.
084     *
085     * @param task The task being validated
086     * @param status Use {@link ValidationStatus#addError(String)} or {@link ValidationStatus#addWarning(String)} to
087     *            provide validation error/warning messages
088     * @throws PackageException
089     */
090    protected abstract void doValidate(Task task, ValidationStatus status) throws PackageException;
091
092    @Override
093    public void validate(Task task, ValidationStatus status) throws PackageException {
094        if (fail != null) {
095            if (new Guard(fail).evaluate(guardVars)) {
096                status.addError("Guard failed for command " + getId() + ": " + fail);
097            }
098        }
099        doValidate(task, status);
100    }
101
102    @Override
103    public Command run(Task task, Map<String, String> prefs) throws PackageException {
104        if (ignore()) {
105            return null;
106        }
107        return doRun(task, prefs);
108    }
109
110    @Override
111    public String getId() {
112        return id;
113    }
114
115    public void setFail(String fail) {
116        this.fail = fail;
117    }
118
119    public void setIgnore(String ignore) {
120        this.ignore = ignore;
121    }
122
123    public boolean ignore() throws PackageException {
124        if (ignore != null) {
125            return new Guard(ignore).evaluate(guardVars);
126        }
127        return false;
128    }
129
130    @Override
131    public void initialize(Element element) throws PackageException {
132        String v = element.getAttribute("fail");
133        if (v.length() > 0) {
134            fail = v;
135        }
136        v = element.getAttribute("ignore");
137        if (v.length() > 0) {
138            ignore = v;
139        }
140        readFrom(element);
141    }
142
143    /**
144     * Must be implemented to initialize the command arguments from an XML fragment.
145     */
146    public abstract void readFrom(Element element) throws PackageException;
147
148}