001/**
002 *
003 * Copyright 2020 Aditya Borikar
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.softwareinfo.form;
018
019import java.util.List;
020
021import org.jivesoftware.smack.util.EqualsUtil;
022import org.jivesoftware.smack.util.HashCode;
023import org.jivesoftware.smackx.mediaelement.element.MediaElement;
024import org.jivesoftware.smackx.xdata.FormField;
025import org.jivesoftware.smackx.xdata.FormFieldChildElement;
026import org.jivesoftware.smackx.xdata.TextSingleFormField;
027import org.jivesoftware.smackx.xdata.form.FilledForm;
028import org.jivesoftware.smackx.xdata.form.Form;
029import org.jivesoftware.smackx.xdata.packet.DataForm;
030import org.jivesoftware.smackx.xdata.packet.DataForm.Type;
031
032/**
033 * {@link Form} that contains the software information.
034 * <br>
035 * Instance of {@link SoftwareInfoForm} can be created using {@link Builder#build()} method.
036 * <br>
037 * To obtain an instance of {@link Builder}, use {@link SoftwareInfoForm#getBuilder()} method.
038 * <br>
039 * An example to illustrate is provided inside SoftwareInfoFormTest inside the test package.
040 */
041public final class SoftwareInfoForm extends FilledForm {
042
043    public static final String FORM_TYPE = "urn:xmpp:dataforms:softwareinfo";
044    public static final String OS = "os";
045    public static final String OS_VERSION = "os_version";
046    public static final String SOFTWARE = "software";
047    public static final String SOFTWARE_VERSION = "software_version";
048    public static final String ICON = "icon";
049
050    private SoftwareInfoForm(DataForm dataForm) {
051        super(dataForm);
052    }
053
054    /**
055     * Returns name of the OS used by client.
056     * <br>
057     * @return os
058     */
059    public String getOS() {
060        return readFirstValue(OS);
061    }
062
063    /**
064     * Returns version of the OS used by client.
065     * <br>
066     * @return os_version
067     */
068    public String getOSVersion() {
069        return readFirstValue(OS_VERSION);
070    }
071
072    /**
073     * Returns name of the software used by client.
074     * <br>
075     * @return software
076     */
077    public String getSoftwareName() {
078        return readFirstValue(SOFTWARE);
079    }
080
081    /**
082     * Returns version of the software used by client.
083     * <br>
084     * @return software_version
085     */
086    public String getSoftwareVersion () {
087        return readFirstValue(SOFTWARE_VERSION);
088    }
089
090    /**
091     * Returns the software icon if used by client.
092     * <br>
093     * @return {@link MediaElement} MediaElement or null
094     */
095    public MediaElement getIcon () {
096        FormField field = getField(ICON);
097        if (field == null) {
098            return null;
099        }
100        FormFieldChildElement media = field.getFormFieldChildElement(MediaElement.QNAME);
101        if (media == null) {
102            return null;
103        }
104        return (MediaElement) media;
105    }
106
107    @Override
108    public boolean equals(Object obj) {
109        return EqualsUtil.equals(this, obj, (equalsBuilder, otherObj) -> {
110            equalsBuilder.append(getDataForm().getType(), otherObj.getDataForm().getType())
111                         .append(getDataForm().getTitle(), otherObj.getDataForm().getTitle())
112                         .append(getDataForm().getReportedData(), otherObj.getDataForm().getReportedData())
113                         .append(getDataForm().getItems(), otherObj.getDataForm().getItems())
114                         .append(getDataForm().getFields(), otherObj.getDataForm().getFields())
115                         .append(getDataForm().getExtensionElements(), otherObj.getDataForm().getExtensionElements());
116        });
117    }
118
119    @Override
120    public int hashCode() {
121        HashCode.Builder builder = HashCode.builder();
122        builder.append(getDataForm().getFields());
123        builder.append(getDataForm().getItems());
124        builder.append(getDataForm().getExtensionElements());
125        return builder.build();
126    }
127
128    /**
129     * Returns a new instance of {@link Builder}.
130     * <br>
131     * @return Builder
132     */
133    public static Builder getBuilder() {
134        return new Builder();
135    }
136
137    /**
138     * Builder class for {@link SoftwareInfoForm}.
139     * <br>
140     * To obtain an instance of {@link Builder}, use {@link SoftwareInfoForm#getBuilder()} method.
141     * <br>
142     * Use appropriate setters to include information inside SoftwareInfoForms.
143     */
144    public static final class Builder {
145        DataForm.Builder dataFormBuilder;
146
147        private Builder() {
148            dataFormBuilder = DataForm.builder(Type.result);
149            TextSingleFormField formField = FormField.buildHiddenFormType(FORM_TYPE);
150            dataFormBuilder.addField(formField);
151        }
152
153        /**
154         * This will allow to include Icon using height, width and Uri's as a
155         * {@link FormField}.
156         * <br>
157         * @param height  Height of the image
158         * @param width   Width of the image
159         * @param uriList List of URIs
160         * @return Builder
161         */
162        public Builder setIcon(int height, int width, List<MediaElement.Uri> uriList) {
163            MediaElement.Builder mediaBuilder = MediaElement.builder();
164            for (MediaElement.Uri uri : uriList) {
165                mediaBuilder.addUri(uri);
166            }
167            MediaElement mediaElement = mediaBuilder.setHeightAndWidth(height, width).build();
168            return setIcon(mediaElement);
169        }
170
171        /**
172         * This will allow to include {@link MediaElement} directly as a
173         * {@link FormField}.
174         * <br>
175         * @param mediaElement MediaElement to be included
176         * @return Builder
177         */
178        public Builder setIcon(MediaElement mediaElement) {
179            FormField.Builder<?, ?> builder = FormField.builder(ICON);
180            builder.addFormFieldChildElement(mediaElement);
181            dataFormBuilder.addField(builder.build());
182            return this;
183        }
184
185        /**
186         * Include Operating System's name as a {@link FormField}.
187         * <br>
188         * @param os Name of the OS
189         * @return Builder
190         */
191        public Builder setOS(String os) {
192            TextSingleFormField.Builder builder = FormField.builder(OS);
193            builder.setValue(os);
194            dataFormBuilder.addField(builder.build());
195            return this;
196        }
197
198        /**
199         * Include Operating System's version as a {@link FormField}.
200         * <br>
201         * @param os_version Version of OS
202         * @return Builder
203         */
204        public Builder setOSVersion(String os_version) {
205            TextSingleFormField.Builder builder = FormField.builder(OS_VERSION);
206            builder.setValue(os_version);
207            dataFormBuilder.addField(builder.build());
208            return this;
209        }
210
211        /**
212         * Include Software name as a {@link FormField}.
213         * <br>
214         * @param software Name of the software
215         * @return Builder
216         */
217        public Builder setSoftware(String software) {
218            TextSingleFormField.Builder builder = FormField.builder(SOFTWARE);
219            builder.setValue(software);
220            dataFormBuilder.addField(builder.build());
221            return this;
222        }
223
224        /**
225         * Include Software Version as a {@link FormField}.
226         * <br>
227         * @param softwareVersion Version of the Software in use
228         * @return Builder
229         */
230        public Builder setSoftwareVersion(String softwareVersion) {
231            TextSingleFormField.Builder builder = FormField.builder(SOFTWARE_VERSION);
232            builder.setValue(softwareVersion);
233            dataFormBuilder.addField(builder.build());
234            return this;
235        }
236
237        /**
238         * Include {@link DataForm} to be encapsulated under SoftwareInfoForm.
239         * <br>
240         * @param dataForm The dataform containing Software Information
241         * @return Builder
242         */
243        public Builder setDataForm(DataForm dataForm) {
244            if (dataForm.getTitle() != null || !dataForm.getItems().isEmpty()
245                    || dataForm.getReportedData() != null || !dataForm.getInstructions().isEmpty()) {
246                throw new IllegalArgumentException("Illegal Arguements for SoftwareInformation");
247            }
248            String formTypeValue = dataForm.getFormType();
249            if (formTypeValue == null) {
250                throw new IllegalArgumentException("FORM_TYPE Formfield missing");
251            }
252            if (!formTypeValue.equals(SoftwareInfoForm.FORM_TYPE)) {
253                throw new IllegalArgumentException("Malformed FORM_TYPE Formfield encountered");
254            }
255            this.dataFormBuilder = dataForm.asBuilder();
256            return this;
257        }
258
259        /**
260         * This method is called to build a {@link SoftwareInfoForm}.
261         * <br>
262         * @return Builder
263         */
264        public SoftwareInfoForm build() {
265            return new SoftwareInfoForm(dataFormBuilder.build());
266        }
267    }
268}