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