• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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