{"sources": [
[1, "/*"],
[2, " * SonarQube, open source software quality management tool."],
[3, " * Copyright (C) 2008-2014 SonarSource"],
[4, " * mailto:contact AT sonarsource DOT com"],
[5, " *"],
[6, " * SonarQube is free software; you can redistribute it and/or"],
[7, " * modify it under the terms of the GNU Lesser General Public"],
[8, " * License as published by the Free Software Foundation; either"],
[9, " * version 3 of the License, or (at your option) any later version."],
[10, " *"],
[11, " * SonarQube is distributed in the hope that it will be useful,"],
[12, " * but WITHOUT ANY WARRANTY; without even the implied warranty of"],
[13, " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU"],
[14, " * Lesser General Public License for more details."],
[15, " *"],
[16, " * You should have received a copy of the GNU Lesser General Public License"],
[17, " * along with this program; if not, write to the Free Software Foundation,"],
[18, " * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."],
[19, " */"],
[20, "package org.sonar.batch.index;"],
[21, ""],
[22, "import com.google.common.collect.Sets;"],
[23, "import com.persistit.Exchange;"],
[24, "import com.persistit.Key;"],
[25, "import com.persistit.KeyFilter;"],
[26, "import com.persistit.exception.PersistitException;"],
[27, "import org.apache.commons.lang.builder.ToStringBuilder;"],
[28, ""],
[29, "import javax.annotation.CheckForNull;"],
[30, ""],
[31, "import java.io.Serializable;"],
[32, "import java.util.Iterator;"],
[33, "import java.util.NoSuchElementException;"],
[34, "import java.util.Set;"],
[35, ""],
[36, "/**"],
[37, " * <p>"],
[38, " * This cache is not thread-safe, due to direct usage of {@link com.persistit.Exchange}"],
[39, " * </p>"],
[40, " */"],
[41, "public class Cache<V extends Serializable> {"],
[42, ""],
[43, " private final String name;"],
[44, " private final Exchange exchange;"],
[45, ""],
[46, " Cache(String name, Exchange exchange) {"],
[47, " this.name = name;"],
[48, " this.exchange = exchange;"],
[49, " }"],
[50, ""],
[51, " public Cache<V> put(Object key, V value) {"],
[52, " resetKey(key);"],
[53, " return doPut(value);"],
[54, " }"],
[55, ""],
[56, " public Cache<V> put(Object firstKey, Object secondKey, V value) {"],
[57, " resetKey(firstKey, secondKey);"],
[58, " return doPut(value);"],
[59, " }"],
[60, ""],
[61, " public Cache<V> put(Object firstKey, Object secondKey, Object thirdKey, V value) {"],
[62, " resetKey(firstKey, secondKey, thirdKey);"],
[63, " return doPut(value);"],
[64, " }"],
[65, ""],
[66, " public Cache<V> put(Object[] key, V value) {"],
[67, " resetKey(key);"],
[68, " return doPut(value);"],
[69, " }"],
[70, ""],
[71, " private Cache<V> doPut(V value) {"],
[72, " try {"],
[73, " exchange.getValue().put(value);"],
[74, " exchange.store();"],
[75, " return this;"],
[76, " } catch (Exception e) {"],
[77, " throw new IllegalStateException(\"Fail to put element in the cache \" + name, e);"],
[78, " }"],
[79, " }"],
[80, ""],
[81, " /**"],
[82, " * Returns the value object associated with keys, or null if not found."],
[83, " */"],
[84, " public V get(Object key) {"],
[85, " resetKey(key);"],
[86, " return doGet();"],
[87, " }"],
[88, ""],
[89, " /**"],
[90, " * Returns the value object associated with keys, or null if not found."],
[91, " */"],
[92, " @CheckForNull"],
[93, " public V get(Object firstKey, Object secondKey) {"],
[94, " resetKey(firstKey, secondKey);"],
[95, " return doGet();"],
[96, " }"],
[97, ""],
[98, " /**"],
[99, " * Returns the value object associated with keys, or null if not found."],
[100, " */"],
[101, " @CheckForNull"],
[102, " public V get(Object firstKey, Object secondKey, Object thirdKey) {"],
[103, " resetKey(firstKey, secondKey, thirdKey);"],
[104, " return doGet();"],
[105, " }"],
[106, ""],
[107, " /**"],
[108, " * Returns the value object associated with keys, or null if not found."],
[109, " */"],
[110, " @CheckForNull"],
[111, " public V get(Object[] key) {"],
[112, " resetKey(key);"],
[113, " return doGet();"],
[114, " }"],
[115, ""],
[116, " @SuppressWarnings(\"unchecked\")"],
[117, " @CheckForNull"],
[118, " private V doGet() {"],
[119, " try {"],
[120, " exchange.fetch();"],
[121, " if (!exchange.getValue().isDefined()) {"],
[122, " return null;"],
[123, " }"],
[124, " return (V) exchange.getValue().get();"],
[125, " } catch (Exception e) {"],
[126, " // TODO add parameters to message"],
[127, " throw new IllegalStateException(\"Fail to get element from cache \" + name, e);"],
[128, " }"],
[129, " }"],
[130, ""],
[131, " public boolean containsKey(Object key) {"],
[132, " resetKey(key);"],
[133, " return doContainsKey();"],
[134, " }"],
[135, ""],
[136, " public boolean containsKey(Object firstKey, Object secondKey) {"],
[137, " resetKey(firstKey, secondKey);"],
[138, " return doContainsKey();"],
[139, " }"],
[140, ""],
[141, " public boolean containsKey(Object firstKey, Object secondKey, Object thirdKey) {"],
[142, " resetKey(firstKey, secondKey, thirdKey);"],
[143, " return doContainsKey();"],
[144, " }"],
[145, ""],
[146, " public boolean containsKey(Object[] key) {"],
[147, " resetKey(key);"],
[148, " return doContainsKey();"],
[149, " }"],
[150, ""],
[151, " private boolean doContainsKey() {"],
[152, " try {"],
[153, " exchange.fetch();"],
[154, " return exchange.isValueDefined();"],
[155, " } catch (Exception e) {"],
[156, " // TODO add parameters to message"],
[157, " throw new IllegalStateException(\"Fail to check if element is in cache \" + name, e);"],
[158, " }"],
[159, " }"],
[160, ""],
[161, " public boolean remove(Object key) {"],
[162, " resetKey(key);"],
[163, " return doRemove();"],
[164, " }"],
[165, ""],
[166, " public boolean remove(Object firstKey, Object secondKey) {"],
[167, " resetKey(firstKey, secondKey);"],
[168, " return doRemove();"],
[169, " }"],
[170, ""],
[171, " public boolean remove(Object firstKey, Object secondKey, Object thirdKey) {"],
[172, " resetKey(firstKey, secondKey, thirdKey);"],
[173, " return doRemove();"],
[174, " }"],
[175, ""],
[176, " public boolean remove(Object[] key) {"],
[177, " resetKey(key);"],
[178, " return doRemove();"],
[179, " }"],
[180, ""],
[181, " private boolean doRemove() {"],
[182, " try {"],
[183, " return exchange.remove();"],
[184, " } catch (Exception e) {"],
[185, " // TODO add parameters to message"],
[186, " throw new IllegalStateException(\"Fail to get element from cache \" + name, e);"],
[187, " }"],
[188, " }"],
[189, ""],
[190, " /**"],
[191, " * Removes everything in the specified group."],
[192, " *"],
[193, " * @param group The group name."],
[194, " */"],
[195, " public Cache<V> clear(Object key) {"],
[196, " resetKey(key);"],
[197, " return doClear();"],
[198, " }"],
[199, ""],
[200, " public Cache<V> clear(Object firstKey, Object secondKey) {"],
[201, " resetKey(firstKey, secondKey);"],
[202, " return doClear();"],
[203, " }"],
[204, ""],
[205, " public Cache<V> clear(Object firstKey, Object secondKey, Object thirdKey) {"],
[206, " resetKey(firstKey, secondKey, thirdKey);"],
[207, " return doClear();"],
[208, " }"],
[209, ""],
[210, " public Cache<V> clear(Object[] key) {"],
[211, " resetKey(key);"],
[212, " return doClear();"],
[213, " }"],
[214, ""],
[215, " private Cache<V> doClear() {"],
[216, " try {"],
[217, " Key to = new Key(exchange.getKey());"],
[218, " to.append(Key.AFTER);"],
[219, " exchange.removeKeyRange(exchange.getKey(), to);"],
[220, " return this;"],
[221, " } catch (Exception e) {"],
[222, " throw new IllegalStateException(\"Fail to clear values from cache \" + name, e);"],
[223, " }"],
[224, " }"],
[225, ""],
[226, " /**"],
[227, " * Clears the default as well as all group caches."],
[228, " */"],
[229, " public void clear() {"],
[230, " try {"],
[231, " exchange.clear();"],
[232, " exchange.removeAll();"],
[233, " } catch (Exception e) {"],
[234, " throw new IllegalStateException(\"Fail to clear cache\", e);"],
[235, " }"],
[236, " }"],
[237, ""],
[238, " /**"],
[239, " * Returns the set of cache keys associated with this group."],
[240, " * TODO implement a lazy-loading equivalent with Iterator/Iterable"],
[241, " *"],
[242, " * @param group The group."],
[243, " * @return The set of cache keys for this group."],
[244, " */"],
[245, " @SuppressWarnings(\"rawtypes\")"],
[246, " public Set keySet(Object key) {"],
[247, " try {"],
[248, " Set<Object> keys = Sets.newLinkedHashSet();"],
[249, " exchange.clear();"],
[250, " Exchange iteratorExchange = new Exchange(exchange);"],
[251, " iteratorExchange.append(key);"],
[252, " iteratorExchange.append(Key.BEFORE);"],
[253, " while (iteratorExchange.next(false)) {"],
[254, " keys.add(iteratorExchange.getKey().indexTo(-1).decode());"],
[255, " }"],
[256, " return keys;"],
[257, " } catch (Exception e) {"],
[258, " throw new IllegalStateException(\"Fail to get keys from cache \" + name, e);"],
[259, " }"],
[260, " }"],
[261, ""],
[262, " @SuppressWarnings(\"rawtypes\")"],
[263, " public Set keySet(Object firstKey, Object secondKey) {"],
[264, " try {"],
[265, " Set<Object> keys = Sets.newLinkedHashSet();"],
[266, " exchange.clear();"],
[267, " Exchange iteratorExchange = new Exchange(exchange);"],
[268, " iteratorExchange.append(firstKey);"],
[269, " iteratorExchange.append(secondKey);"],
[270, " iteratorExchange.append(Key.BEFORE);"],
[271, " while (iteratorExchange.next(false)) {"],
[272, " keys.add(iteratorExchange.getKey().indexTo(-1).decode());"],
[273, " }"],
[274, " return keys;"],
[275, " } catch (Exception e) {"],
[276, " throw new IllegalStateException(\"Fail to get keys from cache \" + name, e);"],
[277, " }"],
[278, " }"],
[279, ""],
[280, " /**"],
[281, " * Returns the set of keys associated with this cache."],
[282, " *"],
[283, " * @return The set containing the keys for this cache."],
[284, " */"],
[285, " public Set<Object> keySet() {"],
[286, " try {"],
[287, " Set<Object> keys = Sets.newLinkedHashSet();"],
[288, " exchange.clear();"],
[289, " Exchange iteratorExchange = new Exchange(exchange);"],
[290, " iteratorExchange.append(Key.BEFORE);"],
[291, " while (iteratorExchange.next(false)) {"],
[292, " keys.add(iteratorExchange.getKey().indexTo(-1).decode());"],
[293, " }"],
[294, " return keys;"],
[295, " } catch (Exception e) {"],
[296, " throw new IllegalStateException(\"Fail to get keys from cache \" + name, e);"],
[297, " }"],
[298, " }"],
[299, ""],
[300, " /**"],
[301, " * Lazy-loading values for given keys"],
[302, " */"],
[303, " public Iterable<V> values(Object firstKey, Object secondKey) {"],
[304, " try {"],
[305, " exchange.clear();"],
[306, " exchange.append(firstKey).append(secondKey).append(Key.BEFORE);"],
[307, " Exchange iteratorExchange = new Exchange(exchange);"],
[308, " KeyFilter filter = new KeyFilter().append(KeyFilter.simpleTerm(firstKey)).append(KeyFilter.simpleTerm(secondKey));"],
[309, " return new ValueIterable<V>(iteratorExchange, filter);"],
[310, " } catch (Exception e) {"],
[311, " throw failToGetValues(e);"],
[312, " }"],
[313, " }"],
[314, ""],
[315, " private IllegalStateException failToGetValues(Exception e) {"],
[316, " return new IllegalStateException(\"Fail to get values from cache \" + name, e);"],
[317, " }"],
[318, ""],
[319, " /**"],
[320, " * Lazy-loading values for a given key"],
[321, " */"],
[322, " public Iterable<V> values(Object firstKey) {"],
[323, " try {"],
[324, " exchange.clear();"],
[325, " exchange.append(firstKey).append(Key.BEFORE);"],
[326, " Exchange iteratorExchange = new Exchange(exchange);"],
[327, " KeyFilter filter = new KeyFilter().append(KeyFilter.simpleTerm(firstKey));"],
[328, " return new ValueIterable<V>(iteratorExchange, filter);"],
[329, " } catch (Exception e) {"],
[330, " throw failToGetValues(e);"],
[331, " }"],
[332, " }"],
[333, ""],
[334, " /**"],
[335, " * Lazy-loading values"],
[336, " */"],
[337, " public Iterable<V> values() {"],
[338, " try {"],
[339, " exchange.clear().append(Key.BEFORE);"],
[340, " Exchange iteratorExchange = new Exchange(exchange);"],
[341, " KeyFilter filter = new KeyFilter().append(KeyFilter.ALL);"],
[342, " return new ValueIterable<V>(iteratorExchange, filter);"],
[343, " } catch (Exception e) {"],
[344, " throw failToGetValues(e);"],
[345, " }"],
[346, " }"],
[347, ""],
[348, " public Iterable<Entry<V>> entries() {"],
[349, " exchange.clear().to(Key.BEFORE);"],
[350, " KeyFilter filter = new KeyFilter().append(KeyFilter.ALL);"],
[351, " return new EntryIterable<V>(new Exchange(exchange), filter);"],
[352, " }"],
[353, ""],
[354, " public Iterable<Entry<V>> entries(Object firstKey) {"],
[355, " exchange.clear().append(firstKey).append(Key.BEFORE);"],
[356, " KeyFilter filter = new KeyFilter().append(KeyFilter.simpleTerm(firstKey));"],
[357, " return new EntryIterable<V>(new Exchange(exchange), filter);"],
[358, " }"],
[359, ""],
[360, " private void resetKey(Object key) {"],
[361, " exchange.clear();"],
[362, " exchange.append(key);"],
[363, " }"],
[364, ""],
[365, " private void resetKey(Object first, Object second) {"],
[366, " exchange.clear();"],
[367, " exchange.append(first).append(second);"],
[368, " }"],
[369, ""],
[370, " private void resetKey(Object first, Object second, Object third) {"],
[371, " exchange.clear();"],
[372, " exchange.append(first).append(second).append(third);"],
[373, " }"],
[374, ""],
[375, " private void resetKey(Object[] keys) {"],
[376, " exchange.clear();"],
[377, " for (Object o : keys) {"],
[378, " exchange.append(o);"],
[379, " }"],
[380, " }"],
[381, ""],
[382, " //"],
[383, " // LAZY ITERATORS AND ITERABLES"],
[384, " //"],
[385, ""],
[386, " private static class ValueIterable<T extends Serializable> implements Iterable<T> {"],
[387, " private final Iterator<T> iterator;"],
[388, ""],
[389, " private ValueIterable(Exchange exchange, KeyFilter keyFilter) {"],
[390, " this.iterator = new ValueIterator<T>(exchange, keyFilter);"],
[391, " }"],
[392, ""],
[393, " @Override"],
[394, " public Iterator<T> iterator() {"],
[395, " return iterator;"],
[396, " }"],
[397, " }"],
[398, ""],
[399, " private static class ValueIterator<T extends Serializable> implements Iterator<T> {"],
[400, " private final Exchange exchange;"],
[401, " private final KeyFilter keyFilter;"],
[402, ""],
[403, " private ValueIterator(Exchange exchange, KeyFilter keyFilter) {"],
[404, " this.exchange = exchange;"],
[405, " this.keyFilter = keyFilter;"],
[406, " }"],
[407, ""],
[408, " @Override"],
[409, " public boolean hasNext() {"],
[410, " try {"],
[411, " return exchange.hasNext(keyFilter);"],
[412, " } catch (PersistitException e) {"],
[413, " throw new IllegalStateException(e);"],
[414, " }"],
[415, " }"],
[416, ""],
[417, " @SuppressWarnings(\"unchecked\")"],
[418, " @Override"],
[419, " public T next() {"],
[420, " try {"],
[421, " exchange.next(keyFilter);"],
[422, " } catch (PersistitException e) {"],
[423, " throw new IllegalStateException(e);"],
[424, " }"],
[425, " if (exchange.getValue().isDefined()) {"],
[426, " return (T) exchange.getValue().get();"],
[427, " }"],
[428, " throw new NoSuchElementException();"],
[429, " }"],
[430, ""],
[431, " @Override"],
[432, " public void remove() {"],
[433, " throw new UnsupportedOperationException(\"Removing an item is not supported\");"],
[434, " }"],
[435, " }"],
[436, ""],
[437, " private static class EntryIterable<T extends Serializable> implements Iterable<Entry<T>> {"],
[438, " private final EntryIterator<T> it;"],
[439, ""],
[440, " private EntryIterable(Exchange exchange, KeyFilter keyFilter) {"],
[441, " it = new EntryIterator<T>(exchange, keyFilter);"],
[442, " }"],
[443, ""],
[444, " @Override"],
[445, " public Iterator<Entry<T>> iterator() {"],
[446, " return it;"],
[447, " }"],
[448, " }"],
[449, ""],
[450, " private static class EntryIterator<T extends Serializable> implements Iterator<Entry<T>> {"],
[451, " private final Exchange exchange;"],
[452, " private final KeyFilter keyFilter;"],
[453, ""],
[454, " private EntryIterator(Exchange exchange, KeyFilter keyFilter) {"],
[455, " this.exchange = exchange;"],
[456, " this.keyFilter = keyFilter;"],
[457, " }"],
[458, ""],
[459, " @Override"],
[460, " public boolean hasNext() {"],
[461, " try {"],
[462, " return exchange.hasNext(keyFilter);"],
[463, " } catch (PersistitException e) {"],
[464, " throw new IllegalStateException(e);"],
[465, " }"],
[466, " }"],
[467, ""],
[468, " @SuppressWarnings(\"unchecked\")"],
[469, " @Override"],
[470, " public Entry<T> next() {"],
[471, " try {"],
[472, " exchange.next(keyFilter);"],
[473, " } catch (PersistitException e) {"],
[474, " throw new IllegalStateException(e);"],
[475, " }"],
[476, " if (exchange.getValue().isDefined()) {"],
[477, " T value = (T) exchange.getValue().get();"],
[478, " Key key = exchange.getKey();"],
[479, " Object[] array = new Object[key.getDepth()];"],
[480, " for (int i = 0; i < key.getDepth(); i++) {"],
[481, " array[i] = key.indexTo(i - key.getDepth()).decode();"],
[482, " }"],
[483, " return new Entry<T>(array, value);"],
[484, " }"],
[485, " throw new NoSuchElementException();"],
[486, " }"],
[487, ""],
[488, " @Override"],
[489, " public void remove() {"],
[490, " throw new UnsupportedOperationException(\"Removing an item is not supported\");"],
[491, " }"],
[492, " }"],
[493, ""],
[494, " public static class Entry<V extends Serializable> {"],
[495, " private final Object[] key;"],
[496, " private final V value;"],
[497, ""],
[498, " Entry(Object[] key, V value) {"],
[499, " this.key = key;"],
[500, " this.value = value;"],
[501, " }"],
[502, ""],
[503, " public Object[] key() {"],
[504, " return key;"],
[505, " }"],
[506, ""],
[507, " @CheckForNull"],
[508, " public V value() {"],
[509, " return value;"],
[510, " }"],
[511, ""],
[512, " @Override"],
[513, " public String toString() {"],
[514, " return ToStringBuilder.reflectionToString(this);"],
[515, " }"],
[516, " }"],
[517, ""],
[518, "}"],
[519, ""]
]}