Home | History | Annotate | Download | only in immutable
      1 /*
      2  * Copyright 2012, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 package org.jf.dexlib2.immutable;
     33 
     34 import com.google.common.collect.*;
     35 import org.jf.dexlib2.base.reference.BaseTypeReference;
     36 import org.jf.dexlib2.iface.Annotation;
     37 import org.jf.dexlib2.iface.ClassDef;
     38 import org.jf.dexlib2.iface.Field;
     39 import org.jf.dexlib2.iface.Method;
     40 import org.jf.dexlib2.util.FieldUtil;
     41 import org.jf.dexlib2.util.MethodUtil;
     42 import org.jf.util.ImmutableConverter;
     43 import org.jf.util.ImmutableUtils;
     44 
     45 import javax.annotation.Nonnull;
     46 import javax.annotation.Nullable;
     47 import java.util.AbstractCollection;
     48 import java.util.Collection;
     49 import java.util.Iterator;
     50 import java.util.List;
     51 
     52 public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
     53     @Nonnull protected final String type;
     54     protected final int accessFlags;
     55     @Nullable protected final String superclass;
     56     @Nonnull protected final ImmutableList<String> interfaces;
     57     @Nullable protected final String sourceFile;
     58     @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations;
     59     @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields;
     60     @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> instanceFields;
     61     @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> directMethods;
     62     @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> virtualMethods;
     63 
     64     public ImmutableClassDef(@Nonnull String type,
     65                              int accessFlags,
     66                              @Nullable String superclass,
     67                              @Nullable Collection<String> interfaces,
     68                              @Nullable String sourceFile,
     69                              @Nullable Collection<? extends Annotation> annotations,
     70                              @Nullable Iterable<? extends Field> fields,
     71                              @Nullable Iterable<? extends Method> methods) {
     72         if (fields == null) {
     73             fields = ImmutableList.of();
     74         }
     75         if (methods == null) {
     76             methods = ImmutableList.of();
     77         }
     78 
     79         this.type = type;
     80         this.accessFlags = accessFlags;
     81         this.superclass = superclass;
     82         this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
     83         this.sourceFile = sourceFile;
     84         this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
     85         this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
     86         this.instanceFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE));
     87         this.directMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT));
     88         this.virtualMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL));
     89     }
     90 
     91     public ImmutableClassDef(@Nonnull String type,
     92                              int accessFlags,
     93                              @Nullable String superclass,
     94                              @Nullable Collection<String> interfaces,
     95                              @Nullable String sourceFile,
     96                              @Nullable Collection<? extends Annotation> annotations,
     97                              @Nullable Iterable<? extends Field> staticFields,
     98                              @Nullable Iterable<? extends Field> instanceFields,
     99                              @Nullable Iterable<? extends Method> directMethods,
    100                              @Nullable Iterable<? extends Method> virtualMethods) {
    101         this.type = type;
    102         this.accessFlags = accessFlags;
    103         this.superclass = superclass;
    104         this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
    105         this.sourceFile = sourceFile;
    106         this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
    107         this.staticFields = ImmutableField.immutableSetOf(staticFields);
    108         this.instanceFields = ImmutableField.immutableSetOf(instanceFields);
    109         this.directMethods = ImmutableMethod.immutableSetOf(directMethods);
    110         this.virtualMethods = ImmutableMethod.immutableSetOf(virtualMethods);
    111     }
    112 
    113     public ImmutableClassDef(@Nonnull String type,
    114                              int accessFlags,
    115                              @Nullable String superclass,
    116                              @Nullable ImmutableList<String> interfaces,
    117                              @Nullable String sourceFile,
    118                              @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations,
    119                              @Nullable ImmutableSortedSet<? extends ImmutableField> staticFields,
    120                              @Nullable ImmutableSortedSet<? extends ImmutableField> instanceFields,
    121                              @Nullable ImmutableSortedSet<? extends ImmutableMethod> directMethods,
    122                              @Nullable ImmutableSortedSet<? extends ImmutableMethod> virtualMethods) {
    123         this.type = type;
    124         this.accessFlags = accessFlags;
    125         this.superclass = superclass;
    126         this.interfaces = ImmutableUtils.nullToEmptyList(interfaces);
    127         this.sourceFile = sourceFile;
    128         this.annotations = ImmutableUtils.nullToEmptySet(annotations);
    129         this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields);
    130         this.instanceFields = ImmutableUtils.nullToEmptySortedSet(instanceFields);
    131         this.directMethods = ImmutableUtils.nullToEmptySortedSet(directMethods);
    132         this.virtualMethods = ImmutableUtils.nullToEmptySortedSet(virtualMethods);
    133     }
    134 
    135     public static ImmutableClassDef of(ClassDef classDef) {
    136         if (classDef instanceof ImmutableClassDef) {
    137             return (ImmutableClassDef)classDef;
    138         }
    139         return new ImmutableClassDef(
    140                 classDef.getType(),
    141                 classDef.getAccessFlags(),
    142                 classDef.getSuperclass(),
    143                 classDef.getInterfaces(),
    144                 classDef.getSourceFile(),
    145                 classDef.getAnnotations(),
    146                 classDef.getStaticFields(),
    147                 classDef.getInstanceFields(),
    148                 classDef.getDirectMethods(),
    149                 classDef.getVirtualMethods());
    150     }
    151 
    152     @Nonnull @Override public String getType() { return type; }
    153     @Override public int getAccessFlags() { return accessFlags; }
    154     @Nullable @Override public String getSuperclass() { return superclass; }
    155     @Nonnull @Override public ImmutableList<String> getInterfaces() { return interfaces; }
    156     @Nullable @Override public String getSourceFile() { return sourceFile; }
    157     @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; }
    158     @Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; }
    159     @Nonnull @Override public ImmutableSet<? extends ImmutableField> getInstanceFields() { return instanceFields; }
    160     @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getDirectMethods() { return directMethods; }
    161     @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getVirtualMethods() { return virtualMethods; }
    162 
    163     @Nonnull
    164     @Override
    165     public Collection<? extends ImmutableField> getFields() {
    166         return new AbstractCollection<ImmutableField>() {
    167             @Nonnull
    168             @Override
    169             public Iterator<ImmutableField> iterator() {
    170                 return Iterators.concat(staticFields.iterator(), instanceFields.iterator());
    171             }
    172 
    173             @Override public int size() {
    174                 return staticFields.size() + instanceFields.size();
    175             }
    176         };
    177     }
    178 
    179     @Nonnull
    180     @Override
    181     public Collection<? extends ImmutableMethod> getMethods() {
    182         return new AbstractCollection<ImmutableMethod>() {
    183             @Nonnull
    184             @Override
    185             public Iterator<ImmutableMethod> iterator() {
    186                 return Iterators.concat(directMethods.iterator(), virtualMethods.iterator());
    187             }
    188 
    189             @Override public int size() {
    190                 return directMethods.size() + virtualMethods.size();
    191             }
    192         };
    193     }
    194 
    195     @Nonnull
    196     public static ImmutableSet<ImmutableClassDef> immutableSetOf(@Nullable Iterable<? extends ClassDef> iterable) {
    197         return CONVERTER.toSet(iterable);
    198     }
    199 
    200     private static final ImmutableConverter<ImmutableClassDef, ClassDef> CONVERTER =
    201             new ImmutableConverter<ImmutableClassDef, ClassDef>() {
    202                 @Override
    203                 protected boolean isImmutable(@Nonnull ClassDef item) {
    204                     return item instanceof ImmutableClassDef;
    205                 }
    206 
    207                 @Nonnull
    208                 @Override
    209                 protected ImmutableClassDef makeImmutable(@Nonnull ClassDef item) {
    210                     return ImmutableClassDef.of(item);
    211                 }
    212             };
    213 }
    214