/*
* Copyright (C) 2009-2015 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.core;
import java.util.HashMap;
import java.util.Map;
/**
* Library of types, which can be used to look up potential matching types.
*
* For example, if you put {@code foo.Spork} and {@code bar.Spork} into the library, and then ask for
* all compatible types given the type {@code Spork}, you'll get both of them, but you'll only
* get the one if you ask for compatible types given {@code foo.Spork}.
* <p>
* When adding {@code foo.Spork}, that FQN (Fully Qualified Name) will be returned as an option for any of these queries:
* <ul><li>foo.Spork</li><li>Spork</li><li>foo.*</li></ul>
*/
public class TypeLibrary {
private final Map<String, String> unqualifiedToQualifiedMap;
private final String unqualified, qualified;
private boolean locked;
public TypeLibrary() {
unqualifiedToQualifiedMap = new HashMap<String, String>();
unqualified = null;
qualified = null;
}
public void lock() {
this.locked = true;
}
private TypeLibrary(String fqnSingleton) {
unqualifiedToQualifiedMap = null;
qualified = fqnSingleton;
int idx = fqnSingleton.lastIndexOf('.');
if (idx == -1) {
unqualified = fqnSingleton;
} else {
unqualified = fqnSingleton.substring(idx + 1);
}
locked = true;
}
public static TypeLibrary createLibraryForSingleType(String fqnSingleton) {
return new TypeLibrary(fqnSingleton);
}
/**
* Add a type to the library.
*
* @param fullyQualifiedTypeName the FQN type name, such as 'java.lang.String'.
*/
public void addType(String fullyQualifiedTypeName) {
if (locked) throw new IllegalStateException("locked");
fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", ".");
int idx = fullyQualifiedTypeName.lastIndexOf('.');
if (idx == -1) throw new IllegalArgumentException(
"Only fully qualified types are allowed (and stuff in the default package is not palatable to us either!)");
String unqualified = fullyQualifiedTypeName.substring(idx + 1);
if (unqualifiedToQualifiedMap == null) throw new IllegalStateException("SingleType library");
unqualifiedToQualifiedMap.put(unqualified, fullyQualifiedTypeName);
unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, fullyQualifiedTypeName);
for (Map.Entry<String, String> e : LombokInternalAliasing.ALIASES.entrySet()) {
if (fullyQualifiedTypeName.equals(e.getValue())) unqualifiedToQualifiedMap.put(e.getKey(), fullyQualifiedTypeName);
}
}
/**
* Translates an unqualified name such as 'String' to 'java.lang.String', _if_ you added 'java.lang.String' to the library via the {@code addType} method.
* Also returns the input if it is equal to a fully qualified name added to this type library.
*
* Returns null if it does not match any type in this type library.
*/
public String toQualified(String typeReference) {
if (unqualifiedToQualifiedMap == null) {
if (typeReference.equals(unqualified) || typeReference.equals(qualified)) return qualified;
for (Map.Entry<String, String> e : LombokInternalAliasing.ALIASES.entrySet()) {
if (e.getKey().equals(typeReference)) return e.getValue();
}
return null;
}
return unqualifiedToQualifiedMap.get(typeReference);
}
}