001/** 002 * 003 * Copyright 2014-2015 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.smack.packet; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Locale; 024import java.util.Map; 025 026import org.jivesoftware.smack.util.Objects; 027import org.jivesoftware.smack.util.PacketUtil; 028import org.jivesoftware.smack.util.XmlStringBuilder; 029 030public class AbstractError { 031 032 protected final String textNamespace; 033 protected final Map<String, String> descriptiveTexts; 034 protected final List<ExtensionElement> extensions; 035 036 037 protected AbstractError(Map<String, String> descriptiveTexts) { 038 this(descriptiveTexts, null); 039 } 040 041 protected AbstractError(Map<String, String> descriptiveTexts, List<ExtensionElement> extensions) { 042 this(descriptiveTexts, null, extensions); 043 } 044 045 protected AbstractError(Map<String, String> descriptiveTexts, String textNamespace, List<ExtensionElement> extensions) { 046 if (descriptiveTexts != null) { 047 this.descriptiveTexts = descriptiveTexts; 048 } else { 049 this.descriptiveTexts = Collections.emptyMap(); 050 } 051 this.textNamespace = textNamespace; 052 if (extensions != null) { 053 this.extensions = extensions; 054 } else { 055 this.extensions = Collections.emptyList(); 056 } 057 } 058 059 /** 060 * Get the descriptive text of this SASLFailure. 061 * <p> 062 * Returns the descriptive text of this SASLFailure in the system default language if possible. May return null. 063 * </p> 064 * 065 * @return the descriptive text or null. 066 */ 067 public String getDescriptiveText() { 068 String defaultLocale = Locale.getDefault().getLanguage(); 069 String descriptiveText = getDescriptiveText(defaultLocale); 070 if (descriptiveText == null) { 071 descriptiveText = getDescriptiveText("en"); 072 if (descriptiveText == null) { 073 descriptiveText = getDescriptiveText(""); 074 } 075 } 076 return descriptiveText; 077 } 078 079 /** 080 * Get the descriptive test of this SASLFailure. 081 * <p> 082 * Returns the descriptive text of this SASLFailure in the given language. May return null if not available. 083 * </p> 084 * 085 * @param xmllang the language. 086 * @return the descriptive text or null. 087 */ 088 public String getDescriptiveText(String xmllang) { 089 Objects.requireNonNull(xmllang, "xmllang must not be null"); 090 return descriptiveTexts.get(xmllang); 091 } 092 093 /** 094 * Returns the first stanza(/packet) extension that matches the specified element name and 095 * namespace, or <tt>null</tt> if it doesn't exist. 096 * 097 * @param elementName the XML element name of the stanza(/packet) extension. 098 * @param namespace the XML element namespace of the stanza(/packet) extension. 099 * @param <PE> type of the ExtensionElement. 100 * @return the extension, or <tt>null</tt> if it doesn't exist. 101 */ 102 public <PE extends ExtensionElement> PE getExtension(String elementName, String namespace) { 103 return PacketUtil.extensionElementFrom(extensions, elementName, namespace); 104 } 105 106 protected void addDescriptiveTextsAndExtensions(XmlStringBuilder xml) { 107 for (Map.Entry<String, String> entry : descriptiveTexts.entrySet()) { 108 String xmllang = entry.getKey(); 109 String text = entry.getValue(); 110 xml.halfOpenElement("text").xmlnsAttribute(textNamespace) 111 .optXmlLangAttribute(xmllang) 112 .rightAngleBracket(); 113 xml.escape(text); 114 xml.closeElement("text"); 115 } 116 for (ExtensionElement packetExtension : extensions) { 117 xml.append(packetExtension.toXML()); 118 } 119 } 120 121 public static abstract class Builder<B extends Builder<B>> { 122 protected String textNamespace; 123 protected Map<String, String> descriptiveTexts; 124 protected List<ExtensionElement> extensions; 125 126 public B setDescriptiveTexts(Map<String, String> descriptiveTexts) { 127 if (descriptiveTexts == null) { 128 this.descriptiveTexts = null; 129 return getThis(); 130 } 131 for (String key : descriptiveTexts.keySet()) { 132 if (key == null) { 133 throw new IllegalArgumentException("descriptiveTexts cannot contain null key"); 134 } 135 } 136 if (this.descriptiveTexts == null) { 137 this.descriptiveTexts = descriptiveTexts; 138 } 139 else { 140 this.descriptiveTexts.putAll(descriptiveTexts); 141 } 142 return getThis(); 143 } 144 145 public B setDescriptiveEnText(String descriptiveEnText) { 146 if (descriptiveTexts == null) { 147 descriptiveTexts = new HashMap<>(); 148 } 149 descriptiveTexts.put("en", descriptiveEnText); 150 return getThis(); 151 } 152 153 public B setTextNamespace(String textNamespace) { 154 this.textNamespace = textNamespace; 155 return getThis(); 156 } 157 158 public B setExtensions(List<ExtensionElement> extensions) { 159 if (this.extensions == null) { 160 this.extensions = extensions; 161 } 162 else { 163 this.extensions.addAll(extensions); 164 } 165 return getThis(); 166 } 167 168 public B addExtension(ExtensionElement extension) { 169 if (extensions == null) { 170 extensions = new ArrayList<>(); 171 } 172 extensions.add(extension); 173 return getThis(); 174 } 175 176 protected abstract B getThis(); 177 } 178}