/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.wink.common.internal.type; /** * Type that represents Java Map types. */ public final class MapType extends TypeBase { /** * Type of keys of Map. */ final JavaType _keyType; /** * Type of values of Map. */ final JavaType _valueType; /* /********************************************************** /* Life-cycle /********************************************************** */ private MapType(Class<?> mapType, JavaType keyT, JavaType valueT) { super(mapType, keyT.hashCode() ^ valueT.hashCode()); _keyType = keyT; _valueType = valueT; } public static MapType construct(Class<?> rawType, JavaType keyT, JavaType valueT) { // nominally component types will be just Object.class return new MapType(rawType, keyT, valueT); } @Override protected JavaType _narrow(Class<?> subclass) { return new MapType(subclass, _keyType, _valueType); } @Override public JavaType narrowContentsBy(Class<?> contentClass) { // Can do a quick check first: if (contentClass == _valueType.getRawClass()) { return this; } JavaType newValueType = _valueType.narrowBy(contentClass); return new MapType(_class, _keyType, newValueType).copyHandlers(this); } public JavaType narrowKey(Class<?> keySubclass) { // Can do a quick check first: if (keySubclass == _keyType.getRawClass()) { return this; } JavaType newKeyType = _keyType.narrowBy(keySubclass); return new MapType(_class, newKeyType, _valueType).copyHandlers(this); } // Since 1.7: @Override public MapType withTypeHandler(Object h) { MapType newInstance = new MapType(_class, _keyType, _valueType); newInstance._typeHandler = h; return newInstance; } // Since 1.7: @Override public MapType withContentTypeHandler(Object h) { return new MapType(_class, _keyType, _valueType.withTypeHandler(h)); } @Override protected String buildCanonicalName() { StringBuilder sb = new StringBuilder(); sb.append(_class.getName()); if (_keyType != null) { sb.append('<'); sb.append(_keyType.toCanonical()); sb.append(','); sb.append(_valueType.toCanonical()); sb.append('>'); } return sb.toString(); } /* /********************************************************** /* Public API /********************************************************** */ @Override public boolean isContainerType() { return true; } @Override public JavaType getKeyType() { return _keyType; } @Override public JavaType getContentType() { return _valueType; } @Override public int containedTypeCount() { return 2; } @Override public JavaType containedType(int index) { if (index == 0) return _keyType; if (index == 1) return _valueType; return null; } /** * Not sure if we should count on this, but type names * for core interfaces are "K" and "V" respectively. * For now let's assume this should work. */ @Override public String containedTypeName(int index) { if (index == 0) return "K"; if (index == 1) return "V"; return null; } @Override public StringBuilder getErasedSignature(StringBuilder sb) { return _classSignature(_class, sb, true); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { _classSignature(_class, sb, false); sb.append('<'); _keyType.getGenericSignature(sb); _valueType.getGenericSignature(sb); sb.append(">;"); return sb; } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public String toString() { return "[map type; class " + _class.getName() + ", " + _keyType + " -> " + _valueType + "]"; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; MapType other = (MapType)o; return (_class == other._class) && _keyType.equals(other._keyType) && _valueType.equals(other._valueType); } }