001/**
002 *
003 * Copyright 2023 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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.jivesoftware.smackx.commands;
018
019import org.jivesoftware.smack.packet.IQ;
020
021import org.jivesoftware.smackx.commands.packet.AdHocCommandData;
022import org.jivesoftware.smackx.xdata.form.FillableForm;
023import org.jivesoftware.smackx.xdata.packet.DataForm;
024
025// TODO: Make this a sealed class once Smack is Java 17 or higher.
026public abstract class AdHocCommandResult {
027
028    private final AdHocCommandData response;
029    private final boolean completed;
030
031    private AdHocCommandResult(AdHocCommandData response, boolean completed) {
032        this.response = response;
033        this.completed = completed;
034    }
035
036    public final AdHocCommandData getResponse() {
037        return response;
038    }
039
040    public final boolean isCompleted() {
041        return completed;
042    }
043
044    public StatusExecuting asExecutingOrThrow() {
045        if (this instanceof StatusExecuting)
046            return (StatusExecuting) this;
047
048        throw new IllegalStateException();
049    }
050
051    public StatusCompleted asCompletedOrThrow() {
052        if (this instanceof StatusCompleted)
053            return (StatusCompleted) this;
054
055        throw new IllegalStateException();
056    }
057
058    public static final class StatusExecuting extends AdHocCommandResult {
059        private StatusExecuting(AdHocCommandData response) {
060            super(response, false);
061            assert response.getStatus() == AdHocCommandData.Status.executing;
062        }
063
064        public FillableForm getFillableForm() {
065            DataForm form = getResponse().getForm();
066            return new FillableForm(form);
067        }
068    }
069
070    public static final class StatusCompleted extends AdHocCommandResult {
071        private StatusCompleted(AdHocCommandData response) {
072            super(response, true);
073            assert response.getStatus() == AdHocCommandData.Status.completed;
074        }
075    }
076
077    /**
078     * This subclass is only used internally by Smack.
079     */
080    @SuppressWarnings("JavaLangClash")
081    static final class Error extends AdHocCommandResult {
082        private Error(AdHocCommandData response) {
083            super(response, false);
084        }
085    }
086
087    public static AdHocCommandResult from(AdHocCommandData response) {
088        IQ.Type iqType = response.getType();
089        if (iqType == IQ.Type.error)
090            return new Error(response);
091
092        assert iqType == IQ.Type.result;
093
094        switch (response.getStatus()) {
095        case executing:
096            return new StatusExecuting(response);
097        case completed:
098            return new StatusCompleted(response);
099        default:
100            throw new IllegalArgumentException();
101        }
102    }
103}