001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.xml; 014 015import static org.apache.juneau.internal.ClassUtils.*; 016import java.util.*; 017import java.util.concurrent.*; 018 019import org.apache.juneau.*; 020import org.apache.juneau.annotation.*; 021import org.apache.juneau.common.internal.*; 022 023/** 024 * Represents a simple namespace mapping between a simple name and URI. 025 * 026 * <p> 027 * In general, the simple name will be used as the XML prefix mapping unless there are conflicts or prefix re-mappings 028 * in the serializer. 029 * 030 * <h5 class='section'>See Also:</h5><ul> 031 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlDetails">XML Details</a> 032 * </ul> 033 */ 034@Bean(sort=true) 035public final class Namespace { 036 037 private static final ConcurrentHashMap<String,Namespace> CACHE = new ConcurrentHashMap<>(); 038 039 040 /** 041 * Create a {@link Namespace} with the specified name and URI. 042 * 043 * <p> 044 * Previously-encountered name/uri pairs return a cached copy. 045 * 046 * @param name The namespace name. See {@link Namespace#getName()}. 047 * @param uri The namespace URI. See {@link Namespace#getUri()}. 048 * @return The namespace object. 049 */ 050 public static Namespace of(String name, String uri) { 051 String key = name + ":" + uri; 052 Namespace n = CACHE.get(key); 053 if (n == null) { 054 n = new Namespace(key, name, uri); 055 Namespace n2 = CACHE.putIfAbsent(key, n); 056 return (n2 == null ? n : n2); 057 } 058 return n; 059 } 060 061 /** 062 * Create a {@link Namespace} from a <js>"name:uri"</js> string pair. 063 * 064 * @param key The key/pair string. 065 * @return The namespace object. 066 */ 067 public static Namespace of(String key) { 068 Namespace n = CACHE.get(key); 069 if (n != null) 070 return n; 071 int i = key.indexOf(':'); 072 if (i == -1) 073 return of(key, null); 074 if (key.startsWith("http://") || key.startsWith("https://")) 075 return of(null, key); 076 return of(key.substring(0, i).trim(), key.substring(i+1).trim()); 077 } 078 079 /** 080 * Converts the specified object into a {@link Namespace} object. 081 * 082 * <p> 083 * Can be any of following types: 084 * <ul> 085 * <li>A {@link Namespace} object 086 * <li>A string containing a name/value pair of the form <js>"name:uri"</js>. 087 * </ul> 088 * 089 * @param o The input. 090 * @return The namespace object, or <jk>null</jk> if the input was <jk>null</jk> or an empty JSON object. 091 */ 092 public static Namespace create(Object o) { 093 if (o == null) 094 return null; 095 if (o instanceof Namespace) 096 return (Namespace)o; 097 if (o instanceof CharSequence) 098 return of(o.toString()); 099 throw new BasicRuntimeException("Invalid object type passed to Namespace.create(Object): ''{0}''", className(o)); 100 } 101 102 /** 103 * Converts the specified object into an array of {@link Namespace} object. 104 * 105 * <p> 106 * Can be any of following types: 107 * <ul> 108 * <li>A {@link Namespace} array 109 * <li>A comma-delimited string with key/value pairs of the form <js>"name:uri"</js>. 110 * <li>A <c>Collection</c> containing any of object that can be passed to {@link #createArray(Object)}. 111 * </ul> 112 * 113 * @param o The input. 114 * @return The namespace objects, or <jk>null</jk> if the input was <jk>null</jk> or an empty JSON object. 115 */ 116 @SuppressWarnings("rawtypes") 117 public static Namespace[] createArray(Object o) { 118 119 if (o instanceof Namespace[]) 120 return (Namespace[])o; 121 122 if (o instanceof String[]) { 123 String[] ss = (String[])o; 124 Namespace[] n = new Namespace[ss.length]; 125 for (int i = 0; i < ss.length; i++) 126 n[i] = create(ss[i]); 127 return n; 128 } 129 130 if (o instanceof CharSequence) { 131 String[] ss = StringUtils.split(o.toString()); 132 Namespace[] n = new Namespace[ss.length]; 133 for (int i = 0; i < ss.length; i++) 134 n[i] = create(ss[i]); 135 return n; 136 } 137 138 if (o instanceof Collection) { 139 Collection c = (Collection)o; 140 Namespace[] n = new Namespace[c.size()]; 141 int i = 0; 142 for (Object o2 : c){ 143 if (o2 instanceof Namespace) 144 n[i++] = (Namespace)o2; 145 else if (o2 instanceof CharSequence) 146 n[i++] = create(o2.toString()); 147 else 148 throw new BasicRuntimeException("Invalid type passed to NamespaceFactory.createArray: ''{0}''", o); 149 } 150 return n; 151 } 152 153 throw new BasicRuntimeException("Invalid type passed to NamespaceFactory.createArray: ''{0}''", o); 154 } 155 156 157 final String key, name, uri; 158 159 /** 160 * Constructor. 161 * 162 * @param name The short name of this schema. 163 * @param uri The URI of this schema. 164 */ 165 private Namespace(String key, String name, String uri) { 166 this.key = key; 167 this.name = name; 168 this.uri = uri; 169 } 170 171 /** 172 * Returns the namespace name. 173 * 174 * @return The namespace name. 175 */ 176 public String getName() { 177 return name; 178 } 179 180 /** 181 * Returns the namespace URI. 182 * 183 * @return The namespace URI. 184 */ 185 public String getUri() { 186 return uri; 187 } 188 189 @Override /* Object */ 190 public String toString() { 191 return key; 192 } 193}