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