| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.solr.handler.dataimport; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.SortedMap; |
| import java.util.TreeMap; |
| |
| public class SortedMapBackedCache implements DIHCache { |
| private SortedMap<Object,List<Map<String,Object>>> theMap = null; |
| private boolean isOpen = false; |
| private boolean isReadOnly = false; |
| String primaryKeyName = null; |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void add(Map<String,Object> rec) { |
| checkOpen(true); |
| checkReadOnly(); |
| |
| if (rec == null || rec.size() == 0) { |
| return; |
| } |
| |
| if (primaryKeyName == null) { |
| primaryKeyName = rec.keySet().iterator().next(); |
| } |
| |
| Object pk = rec.get(primaryKeyName); |
| if (pk instanceof Collection<?>) { |
| Collection<Object> c = (Collection<Object>) pk; |
| if (c.size() != 1) { |
| throw new RuntimeException( |
| "The primary key must have exactly 1 element."); |
| } |
| pk = c.iterator().next(); |
| } |
| //Rows with null keys are not added. |
| if(pk==null) { |
| return; |
| } |
| List<Map<String,Object>> thisKeysRecs = theMap.get(pk); |
| if (thisKeysRecs == null) { |
| thisKeysRecs = new ArrayList<>(); |
| theMap.put(pk, thisKeysRecs); |
| } |
| thisKeysRecs.add(rec); |
| } |
| |
| private void checkOpen(boolean shouldItBe) { |
| if (!isOpen && shouldItBe) { |
| throw new IllegalStateException( |
| "Must call open() before using this cache."); |
| } |
| if (isOpen && !shouldItBe) { |
| throw new IllegalStateException("The cache is already open."); |
| } |
| } |
| |
| private void checkReadOnly() { |
| if (isReadOnly) { |
| throw new IllegalStateException("Cache is read-only."); |
| } |
| } |
| |
| @Override |
| public void close() { |
| isOpen = false; |
| } |
| |
| @Override |
| public void delete(Object key) { |
| checkOpen(true); |
| checkReadOnly(); |
| if(key==null) { |
| return; |
| } |
| theMap.remove(key); |
| } |
| |
| @Override |
| public void deleteAll() { |
| deleteAll(false); |
| } |
| |
| private void deleteAll(boolean readOnlyOk) { |
| if (!readOnlyOk) { |
| checkReadOnly(); |
| } |
| if (theMap != null) { |
| theMap.clear(); |
| } |
| } |
| |
| @Override |
| public void destroy() { |
| deleteAll(true); |
| theMap = null; |
| isOpen = false; |
| } |
| |
| @Override |
| public void flush() { |
| checkOpen(true); |
| checkReadOnly(); |
| } |
| |
| @Override |
| public Iterator<Map<String,Object>> iterator(Object key) { |
| checkOpen(true); |
| if(key==null) { |
| return null; |
| } |
| if(key instanceof Iterable<?>) { |
| List<Map<String,Object>> vals = new ArrayList<>(); |
| Iterator<?> iter = ((Iterable<?>) key).iterator(); |
| while(iter.hasNext()) { |
| List<Map<String,Object>> val = theMap.get(iter.next()); |
| if(val!=null) { |
| vals.addAll(val); |
| } |
| } |
| if(vals.size()==0) { |
| return null; |
| } |
| return vals.iterator(); |
| } |
| List<Map<String,Object>> val = theMap.get(key); |
| if (val == null) { |
| return null; |
| } |
| return val.iterator(); |
| } |
| |
| @Override |
| public Iterator<Map<String,Object>> iterator() { |
| return new Iterator<Map<String, Object>>() { |
| private Iterator<Map.Entry<Object,List<Map<String,Object>>>> theMapIter; |
| private List<Map<String,Object>> currentKeyResult = null; |
| private Iterator<Map<String,Object>> currentKeyResultIter = null; |
| |
| { |
| theMapIter = theMap.entrySet().iterator(); |
| } |
| |
| @Override |
| public boolean hasNext() { |
| if (currentKeyResultIter != null) { |
| if (currentKeyResultIter.hasNext()) { |
| return true; |
| } else { |
| currentKeyResult = null; |
| currentKeyResultIter = null; |
| } |
| } |
| |
| Map.Entry<Object,List<Map<String,Object>>> next = null; |
| if (theMapIter.hasNext()) { |
| next = theMapIter.next(); |
| currentKeyResult = next.getValue(); |
| currentKeyResultIter = currentKeyResult.iterator(); |
| if (currentKeyResultIter.hasNext()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public Map<String,Object> next() { |
| if (currentKeyResultIter != null) { |
| if (currentKeyResultIter.hasNext()) { |
| return currentKeyResultIter.next(); |
| } else { |
| currentKeyResult = null; |
| currentKeyResultIter = null; |
| } |
| } |
| |
| Map.Entry<Object,List<Map<String,Object>>> next = null; |
| if (theMapIter.hasNext()) { |
| next = theMapIter.next(); |
| currentKeyResult = next.getValue(); |
| currentKeyResultIter = currentKeyResult.iterator(); |
| if (currentKeyResultIter.hasNext()) { |
| return currentKeyResultIter.next(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| @Override |
| public void open(Context context) { |
| checkOpen(false); |
| isOpen = true; |
| if (theMap == null) { |
| theMap = new TreeMap<>(); |
| } |
| |
| String pkName = CachePropertyUtil.getAttributeValueAsString(context, |
| DIHCacheSupport.CACHE_PRIMARY_KEY); |
| if (pkName != null) { |
| primaryKeyName = pkName; |
| } |
| isReadOnly = false; |
| String readOnlyStr = CachePropertyUtil.getAttributeValueAsString(context, |
| DIHCacheSupport.CACHE_READ_ONLY); |
| if ("true".equalsIgnoreCase(readOnlyStr)) { |
| isReadOnly = true; |
| } |
| } |
| |
| } |