/ app / src / main / java / com / reandroid / identifiers / IdentifierMap.java
IdentifierMap.java
  1  /*
  2   *  Copyright (C) 2022 github.com/REAndroid
  3   *
  4   *  Licensed under the Apache License, Version 2.0 (the "License");
  5   *  you may not use this file except in compliance with the License.
  6   *  You may obtain a copy of the License at
  7   *
  8   *      http://www.apache.org/licenses/LICENSE-2.0
  9   *
 10   * Unless required by applicable law or agreed to in writing, software
 11   * distributed under the License is distributed on an "AS IS" BASIS,
 12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13   * See the License for the specific language governing permissions and
 14   * limitations under the License.
 15   */
 16  package com.reandroid.identifiers;
 17  
 18  import java.util.*;
 19  
 20  class IdentifierMap<CHILD extends Identifier> extends Identifier
 21          implements Comparator<CHILD> {
 22      private final Object mLock = new Object();
 23      private final Map<Integer, CHILD> idMap;
 24      private final Map<String, CHILD> nameMap;
 25      private boolean mCaseInsensitive;
 26      private int maxId;
 27  
 28      public IdentifierMap(int id, String name){
 29          super(id, name);
 30          this.idMap = new HashMap<>();
 31          this.nameMap = new HashMap<>();
 32          this.mCaseInsensitive = CASE_INSENSITIVE_FS;
 33      }
 34  
 35      public int getMaxId(){
 36          return maxId;
 37      }
 38      public List<CHILD> listDuplicates(){
 39          List<CHILD> results = new ArrayList<>();
 40          Map<String, CHILD> uniques = new HashMap<>();
 41          for(CHILD item : getItems()){
 42              String name = item.getName();
 43              if(isCaseInsensitive()){
 44                  name = name.toLowerCase();
 45              }
 46              if(uniques.containsKey(name)){
 47                  results.add(item);
 48                  results.add(uniques.get(name));
 49              }else {
 50                  uniques.put(name, item);
 51              }
 52          }
 53          results.sort(this);
 54          return results;
 55      }
 56      public boolean hasDuplicates(){
 57          Set<String> uniques = new HashSet<>();
 58          for(CHILD item : getItems()){
 59              String name = item.getName();
 60              if(uniques.contains(name)){
 61                  return true;
 62              }else {
 63                  uniques.add(name);
 64              }
 65          }
 66          return false;
 67      }
 68      public List<String> listNames(){
 69          List<String> results = new ArrayList<>(size());
 70          for(CHILD item : list()){
 71              results.add(item.getName());
 72          }
 73          return results;
 74      }
 75      public List<CHILD> list(){
 76          List<CHILD> childList = new ArrayList<>(getItems());
 77          childList.sort(this);
 78          return childList;
 79      }
 80      public Collection<CHILD> getItems(){
 81          synchronized (mLock){
 82              return this.idMap.values();
 83          }
 84      }
 85      public void clear(){
 86          synchronized (mLock){
 87              this.idMap.clear();
 88              this.nameMap.clear();
 89          }
 90      }
 91      public CHILD getByTag(Object tag){
 92          for(CHILD item : getItems()){
 93              if(Objects.equals(tag, item.getTag())){
 94                  return item;
 95              }
 96          }
 97          return null;
 98      }
 99      public int size(){
100          synchronized (mLock){
101              return this.idMap.size();
102          }
103      }
104      public CHILD get(String childName){
105          synchronized (mLock){
106              return this.nameMap.get(childName);
107          }
108      }
109      public CHILD get(int childId){
110          synchronized (mLock){
111              return this.idMap.get(childId);
112          }
113      }
114      public void remove(CHILD entry){
115          synchronized (mLock){
116              if(entry == null){
117                  return;
118              }
119              this.idMap.remove(entry.getId());
120              this.nameMap.remove(entry.getName());
121          }
122      }
123      public CHILD add(CHILD child){
124          synchronized (mLock){
125              if(child == null){
126                  return null;
127              }
128              child.setParent(this);
129              Integer entryId = child.getId();
130              CHILD exist = this.idMap.get(entryId);
131              if(exist != null){
132                  if(exist.getName() == null){
133                      exist.setName(child.getName());
134                      addNameMap(exist);
135                  }
136                  return exist;
137              }
138              this.idMap.put(entryId, child);
139              if(entryId > maxId){
140                  maxId = entryId;
141              }
142              addNameMap(child);
143              return child;
144          }
145      }
146      public void reloadNameMap(){
147          synchronized (mLock){
148              this.nameMap.clear();
149              for(CHILD child : idMap.values()){
150                  addNameMap(child);
151              }
152          }
153      }
154      private void addNameMap(CHILD child){
155          String childName = child.getName();
156          if(childName == null){
157              return;
158          }
159          CHILD exist = this.nameMap.get(childName);
160          if(exist != null){
161              return;
162          }
163          this.nameMap.put(childName, child);
164      }
165      private boolean isCaseInsensitive(){
166          return mCaseInsensitive;
167      }
168      void setCaseInsensitive(boolean caseInsensitive){
169          mCaseInsensitive = caseInsensitive;
170      }
171      @Override
172      public int compare(CHILD child1, CHILD child2) {
173          return child1.compareTo(child2);
174      }
175      @Override
176      public String toString(){
177          return super.toString() + " entries = " + size();
178      }
179  }