001/**
002 *
003 * Copyright 2019-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.smack.packet;
018
019import org.jivesoftware.smack.util.ParserUtils;
020import org.jivesoftware.smack.util.StringUtils;
021import org.jivesoftware.smack.xml.XmlPullParser;
022
023public class XmlEnvironment {
024
025    public static final XmlEnvironment EMPTY = new XmlEnvironment((String) null);
026
027    private final String namespace;
028    private final String language;
029    private final XmlEnvironment next;
030
031    private transient boolean effectiveNamespaceDetermined;
032    private transient boolean effectiveLanguageDetermined;
033    private transient String effectiveNamespace;
034    private transient String effectiveLanguage;
035
036    public XmlEnvironment(String namespace) {
037        this(namespace, null);
038    }
039
040    public XmlEnvironment(String namespace, String language) {
041        this(namespace, language, null);
042    }
043
044    private XmlEnvironment(Builder builder) {
045        this(builder.namespace, builder.language, builder.next);
046    }
047
048    public XmlEnvironment(String namespace, String language, XmlEnvironment next) {
049        this.namespace = namespace;
050        this.language = language;
051        this.next = next;
052    }
053
054    public String getNamespace() {
055        return namespace;
056    }
057
058    public String getEffectiveNamespace() {
059        if (effectiveNamespaceDetermined) {
060            return effectiveNamespace;
061        }
062
063        if (StringUtils.isNotEmpty(namespace)) {
064            effectiveNamespace = namespace;
065        } else if (next != null) {
066            effectiveNamespace = next.getEffectiveNamespace();
067        }
068
069        effectiveNamespaceDetermined = true;
070        return effectiveNamespace;
071    }
072
073    public String getEffectiveNamespaceOrUse(String namespace) {
074        String effectiveNamespace = getEffectiveNamespace();
075        if (StringUtils.isNullOrEmpty(effectiveNamespace)) {
076            return namespace;
077        }
078        return effectiveNamespace;
079    }
080
081    public boolean effectiveNamespaceEquals(String namespace) {
082        String effectiveNamespace = getEffectiveNamespace();
083        if (effectiveNamespace == null) {
084            return false;
085        }
086        return effectiveNamespace.equals(namespace);
087    }
088
089    public String getLanguage() {
090        return language;
091    }
092
093    public String getEffectiveLanguage() {
094        if (effectiveLanguageDetermined) {
095            return effectiveLanguage;
096        }
097
098        if (StringUtils.isNotEmpty(language)) {
099            effectiveLanguage = language;
100        } else if (next != null) {
101            effectiveLanguage = next.getEffectiveLanguage();
102        }
103
104        effectiveLanguageDetermined = true;
105        return effectiveLanguage;
106    }
107
108    public boolean effectiveLanguageEquals(String language) {
109        String effectiveLanguage = getEffectiveLanguage();
110        if (effectiveLanguage == null) {
111            return false;
112        }
113        return effectiveLanguage.equals(language);
114    }
115
116    private transient String toStringCache;
117
118    @Override
119    public String toString() {
120        if (toStringCache == null) {
121            StringBuilder sb = new StringBuilder();
122            sb.append(XmlEnvironment.class.getSimpleName()).append(' ');
123            sb.append("xmlns=").append(getEffectiveNamespace()).append(' ');
124            sb.append("xmllang=").append(getEffectiveLanguage()).append(' ');
125
126            toStringCache = sb.toString();
127        }
128        return toStringCache;
129    }
130
131    public static XmlEnvironment from(XmlPullParser parser) {
132        return from(parser, null);
133    }
134
135    public static XmlEnvironment from(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) {
136        String namespace = parser.getDefaultNamespace();
137        String xmlLang = ParserUtils.getXmlLang(parser);
138        return new XmlEnvironment(namespace, xmlLang, outerXmlEnvironment);
139    }
140
141    public static Builder builder() {
142        return new Builder();
143    }
144
145    public static class Builder {
146        private String namespace;
147        private String language;
148        private XmlEnvironment next;
149
150        public Builder withNamespace(String namespace) {
151            this.namespace = namespace;
152            return this;
153        }
154
155        public Builder withLanguage(String language) {
156            this.language = language;
157            return this;
158        }
159
160        public Builder withNext(XmlEnvironment next) {
161            this.next = next;
162            return this;
163        }
164
165        public Builder with(StreamOpen streamOpen) {
166            withNamespace(streamOpen.getNamespace());
167            withLanguage(streamOpen.getLanguage());
168            return this;
169        }
170
171        public XmlEnvironment build() {
172            return new XmlEnvironment(this);
173        }
174    }
175}