001/*
002 * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.connect.update.task.standalone.commands;
020
021import java.util.HashMap;
022import java.util.Map;
023
024import org.w3c.dom.Element;
025
026import org.nuxeo.connect.update.PackageException;
027import org.nuxeo.connect.update.ValidationStatus;
028import org.nuxeo.connect.update.task.Command;
029import org.nuxeo.connect.update.task.Task;
030import org.nuxeo.connect.update.task.guards.Guard;
031
032/**
033 * All commands have 2 attributes: fail and ignore which are EL expressions.
034 * <p>
035 * If ignore is defined and evaluated to true then the command will be ignored (null is returned as the inverse command)
036 * If fail is defined and evaluated to true then the validation fails.
037 * <p>
038 * Commands extending this class must implement the {@link #doRun} and {@link #doValidate} methods instead of the one in
039 * the interface. These methods are first testing for ignore and fail guards and then if needed delegated to the doXXX
040 * method versions.
041 *
042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
043 */
044public abstract class AbstractCommand implements Command {
045
046    /**
047     * List of files which must never be deleted at runtime.
048     *
049     * @since 5.5
050     */
051    protected final String id;
052
053    protected final Map<String, Object> guardVars;
054
055    protected String fail;
056
057    protected String ignore;
058
059    protected AbstractCommand(String id) {
060        this.id = id;
061        guardVars = new HashMap<>();
062    }
063
064    public AbstractCommand(AbstractCommand command) {
065        this.id = command.id;
066        guardVars = command.guardVars;
067    }
068
069    @Override
070    public boolean isPostInstall() {
071        return false;
072    }
073
074    /**
075     * Override to implement command actions
076     *
077     * @param task
078     * @param prefs
079     * @return Rollback command
080     * @throws PackageException
081     */
082    protected abstract Command doRun(Task task, Map<String, String> prefs) throws PackageException;
083
084    /**
085     * Override to implement validation.
086     *
087     * @param task The task being validated
088     * @param status Use {@link ValidationStatus#addError(String)} or {@link ValidationStatus#addWarning(String)} to
089     *            provide validation error/warning messages
090     * @throws PackageException
091     */
092    protected abstract void doValidate(Task task, ValidationStatus status) throws PackageException;
093
094    @Override
095    public void validate(Task task, ValidationStatus status) throws PackageException {
096        if (fail != null) {
097            if (new Guard(fail).evaluate(guardVars)) {
098                status.addError("Guard failed for command " + getId() + ": " + fail);
099            }
100        }
101        doValidate(task, status);
102    }
103
104    @Override
105    public Command run(Task task, Map<String, String> prefs) throws PackageException {
106        if (ignore()) {
107            return null;
108        }
109        return doRun(task, prefs);
110    }
111
112    @Override
113    public String getId() {
114        return id;
115    }
116
117    public void setFail(String fail) {
118        this.fail = fail;
119    }
120
121    public void setIgnore(String ignore) {
122        this.ignore = ignore;
123    }
124
125    public boolean ignore() throws PackageException {
126        if (ignore != null) {
127            return new Guard(ignore).evaluate(guardVars);
128        }
129        return false;
130    }
131
132    @Override
133    public void initialize(Element element) throws PackageException {
134        String v = element.getAttribute("fail");
135        if (v.length() > 0) {
136            fail = v;
137        }
138        v = element.getAttribute("ignore");
139        if (v.length() > 0) {
140            ignore = v;
141        }
142        readFrom(element);
143    }
144
145    /**
146     * Must be implemented to initialize the command arguments from an XML fragment.
147     */
148    public abstract void readFrom(Element element) throws PackageException;
149
150}