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