TypeMetadata.java revision 2646:ff1998c1ecab
1/* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights 3 * reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE 4 * HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27package com.sun.tools.javac.code; 28 29import com.sun.tools.javac.util.Assert; 30import com.sun.tools.javac.util.List; 31import java.util.EnumMap; 32import java.util.HashSet; 33import java.util.Map; 34import java.util.Set; 35 36/** 37 * A super-interface for all type metadata elements. Metadata classes 38 * can be created for any metadata on types with the following 39 * properties: 40 * 41 * <ul> 42 * <li>They have a default value (preferably empty)</li> 43 * <li>The field is usually the default value</li> 44 * <li>Different values of the field are visible, and denote distinct 45 * types</li> 46 * </ul> 47 */ 48public class TypeMetadata { 49 50 public static final TypeMetadata empty = new TypeMetadata(); 51 private final EnumMap<TypeMetadata.Element.Kind, TypeMetadata.Element> contents; 52 53 private TypeMetadata() { 54 contents = new EnumMap<Element.Kind, Element>(Element.Kind.class); 55 } 56 57 public TypeMetadata(final Element elem) { 58 this(); 59 contents.put(elem.kind(), elem); 60 } 61 62 public TypeMetadata(final TypeMetadata other) { 63 contents = other.contents.clone(); 64 } 65 66 public TypeMetadata copy() { 67 return new TypeMetadata(this); 68 } 69 70 public TypeMetadata combine(final Element elem) { 71 final TypeMetadata out = new TypeMetadata(this); 72 final Element.Kind key = elem.kind(); 73 if (contents.containsKey(key)) { 74 out.add(key, this.contents.get(key).combine(elem)); 75 } else { 76 out.add(key, elem); 77 } 78 return out; 79 } 80 81 public TypeMetadata combine(final TypeMetadata other) { 82 final TypeMetadata out = new TypeMetadata(); 83 final Set<Element.Kind> keys = new HashSet<>(this.contents.keySet()); 84 keys.addAll(other.contents.keySet()); 85 86 for(final Element.Kind key : keys) { 87 if (this.contents.containsKey(key)) { 88 if (other.contents.containsKey(key)) { 89 out.add(key, this.contents.get(key).combine(other.contents.get(key))); 90 } else { 91 out.add(key, this.contents.get(key)); 92 } 93 } else if (other.contents.containsKey(key)) { 94 out.add(key, other.contents.get(key)); 95 } 96 } 97 return out; 98 } 99 100 public Element get(final Element.Kind kind) { 101 return contents.get(kind); 102 } 103 104 public boolean isEmpty() { 105 return contents.isEmpty(); 106 } 107 108 private void add(final Element.Kind kind, final Element elem) { 109 contents.put(kind, elem); 110 } 111 112 private void addAll(final Map<? extends Element.Kind,? extends Element> m) { 113 contents.putAll(m); 114 } 115 116 public interface Element { 117 118 public enum Kind { 119 ANNOTATIONS; 120 } 121 122 /** 123 * Get the kind of metadata this object represents 124 */ 125 public Kind kind(); 126 127 /** 128 * Combine this type metadata with another metadata of the 129 * same kind. 130 * 131 * @param other The metadata with which to combine this one. 132 * @return The combined metadata. 133 */ 134 public Element combine(Element other); 135 } 136 137 /** 138 * A type metadata object holding type annotations. 139 */ 140 public static class Annotations implements Element { 141 private final List<Attribute.TypeCompound> annos; 142 143 public Annotations(final List<Attribute.TypeCompound> annos) { 144 this.annos = annos; 145 } 146 147 /** 148 * Get the type annotations contained in this metadata. 149 * 150 * @return The annotations. 151 */ 152 public List<Attribute.TypeCompound> getAnnotations() { 153 return annos; 154 } 155 156 @Override 157 public Annotations combine(final Element other) { 158 // Temporary: we should append the lists, but that won't 159 // work with type annotations today. Instead, we replace 160 // the list. 161 return new Annotations(((Annotations) other).annos); 162 } 163 164 @Override 165 public Kind kind() { return Kind.ANNOTATIONS; } 166 167 @Override 168 public String toString() { return "ANNOTATIONS { " + annos + " }"; } 169 } 170 171} 172