/* Software Name : AsmDex * Version : 1.0 * * Copyright © 2012 France Télécom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.ow2.asmdex.structureWriter; /** * A Class representing an annotation_set_ref_list structure. * * It possesses the Annotation_set_item that EACH argument of a Method has. Dalvik handles them this way : * If AT LEAST one argument of a Method is annotated, then all the arguments are stored here. * The non-annotated arguments have an annotation_set_item that has a size of 0. * * Since all the arguments must be stored, the constructor requires the number of parameters of the Method * this annotation_set_ref_list belongs. * * When all the parameters have been filled (which can be done in several passes, if several annotations), the * annotation_set_ref_list HAS to be "closed" (through the close() method) so that empty parameters can be * filled with empty annotation_set_items. * * @author Julien Névo * */ public class AnnotationSetRefList { /** * Array of annotation_set_item, each item for one parameter. */ private AnnotationSetItem[] annotationSetItems; /** * Number of parameters of the Methods it belongs (return type not included). */ final private int nbParameters; /** * Indicates how many annotation_set_items are actually used (the rest being empty). */ private int nbAnnotationSetItemsUsed = 0; /** * The Method this structure belongs to. */ final private Method method; /** * Constructor of an annotation_set_ref_list. * @param nbParameters number of parameters of the Methods it belongs to (return type not included). * @param method the Method this annotation_set_ref_list belongs to. */ public AnnotationSetRefList(int nbParameters, Method method) { this.nbParameters = nbParameters; this.method = method; annotationSetItems = new AnnotationSetItem[nbParameters]; } /** * An empty annotation_set_item, used to fill unused parameters. */ private static AnnotationSetItem emptyAnnotationSetItem = null; // ---------------------------------------------- // Public methods. // ---------------------------------------------- /** * Adds an annotation_item to the given parameter. * @param parameterIndex the zero-based index of the parameter. * @param annotationItem the annotation_item to add. */ public void addAnnotationItem(int parameterIndex, AnnotationItem annotationItem) { if (parameterIndex >= nbParameters) { try { throw new Exception("Annotation Parameter index >= Parameter count of this method."); } catch (Exception e) { e.printStackTrace(); } } AnnotationSetItem annotationSetItem; // Does the annotation_set_item for this parameter exists ? If not, we must create it. if (annotationSetItems[parameterIndex] == null) { annotationSetItem = new AnnotationSetItem(); nbAnnotationSetItemsUsed++; } else { annotationSetItem = annotationSetItems[parameterIndex]; } annotationSetItem.addAnnotationItem(annotationItem); annotationSetItems[parameterIndex] = annotationSetItem; } /** * Fill the empty parameters with an empty annotation_set_item. This has to be done once before * encoding the Dex file. */ public void close() { for (int i = 0, size = annotationSetItems.length; i < size; i++) { if (annotationSetItems[i] == null) { annotationSetItems[i] = getEmptyAnnotationSetItem(); } } } // ---------------------------------------------- // Private Methods. // ---------------------------------------------- /** * Provides an empty annotation_set_item. */ private static AnnotationSetItem getEmptyAnnotationSetItem() { if (emptyAnnotationSetItem == null) { emptyAnnotationSetItem = new AnnotationSetItem(); } return emptyAnnotationSetItem; } // ---------------------------------------------- // Getters. // ---------------------------------------------- /** * Returns an array containing, for each parameters, an annotation_set_item. All the parameters have an * annotation_set_items. However, it can have an empty size of the parameter is not annotated. * @return a Map containing, for each parameters, an annotation_set_item. */ public AnnotationSetItem[] getAnnotationSetItems() { return annotationSetItems; } /** * Returns the annotation_set_item of the given parameter index. * @param parameterIndex the zero-based parameter index. * @return the annotation_set_item of the given parameter index. */ public AnnotationSetItem getAnnotationSetItem(int parameterIndex) { return annotationSetItems[parameterIndex]; } /** * Returns the number of annotation_set_items in the structure. Represents ALL the arguments, even * those who were not annotated. * @return the number of annotation_set_items in the structure. */ public int getNbAnnotationSetItem() { return annotationSetItems.length; } /** * Returns the number of annotation_set_items that are not empty or null. * @return the number of annotation_set_items that are not empty or null. */ public int getNbAnnotationSetItemsUsed() { return nbAnnotationSetItemsUsed; } /** * Returns the Method this structure belongs to. * @return the Method this structure belongs to. */ public Method getMethod() { return method; } // ---------------------------------------------- // Overridden methods. // ---------------------------------------------- @Override public int hashCode() { // Caching the hashcode is useless (not enough calls). return java.util.Arrays.hashCode(annotationSetItems); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof AnnotationSetRefList) { AnnotationSetRefList asr = (AnnotationSetRefList)obj; // Patch for part of bug316398 : return method.equals(asr.method) && java.util.Arrays.equals(annotationSetItems, asr.annotationSetItems); } return false; } }