1 package org.jf.dexlib2.builder; 2 3 import com.google.common.collect.ImmutableList; 4 5 import javax.annotation.Nonnull; 6 import javax.annotation.Nullable; 7 import java.util.*; 8 9 public abstract class LocatedItems<T extends ItemWithLocation> { 10 // We end up creating and keeping around a *lot* of MethodLocation objects 11 // when building a new dex file, so it's worth the trouble of lazily creating 12 // the labels and debugItems lists only when they are needed 13 @Nullable 14 private List<T> items = null; 15 16 @Nonnull getItems()17 private List<T> getItems() { 18 if (items == null) { 19 return ImmutableList.of(); 20 } 21 return items; 22 } 23 getModifiableItems(MethodLocation newItemsLocation)24 public Set<T> getModifiableItems(MethodLocation newItemsLocation) { 25 return new AbstractSet<T>() { 26 @Nonnull 27 @Override 28 public Iterator<T> iterator() { 29 final Iterator<T> it = getItems().iterator(); 30 31 return new Iterator<T>() { 32 private @Nullable 33 T currentItem = null; 34 35 @Override 36 public boolean hasNext() { 37 return it.hasNext(); 38 } 39 40 @Override 41 public T next() { 42 currentItem = it.next(); 43 return currentItem; 44 } 45 46 @Override 47 public void remove() { 48 if (currentItem != null) { 49 currentItem.setLocation(null); 50 } 51 it.remove(); 52 } 53 }; 54 } 55 56 @Override 57 public int size() { 58 return getItems().size(); 59 } 60 61 @Override 62 public boolean add(@Nonnull T item) { 63 if (item.isPlaced()) { 64 throw new IllegalArgumentException(getAddLocatedItemError()); 65 } 66 item.setLocation(newItemsLocation); 67 addItem(item); 68 return true; 69 } 70 }; 71 } 72 73 private void addItem(@Nonnull T item) { 74 if (items == null) { 75 items = new ArrayList<>(1); 76 } 77 items.add(item); 78 } 79 80 protected abstract String getAddLocatedItemError(); 81 82 public void mergeItemsIntoNext(@Nonnull MethodLocation nextLocation, LocatedItems<T> otherLocatedItems) { 83 if (otherLocatedItems == this) { 84 return; 85 } 86 if (items != null) { 87 for (T item : items) { 88 item.setLocation(nextLocation); 89 } 90 List<T> mergedItems = items; 91 mergedItems.addAll(otherLocatedItems.getItems()); 92 otherLocatedItems.items = mergedItems; 93 items = null; 94 } 95 } 96 } 97