PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/astyanax-cassandra/src/main/java/com/netflix/astyanax/model/AbstractComposite.java

http://github.com/Netflix/astyanax
Java | 731 lines | 585 code | 123 blank | 23 comment | 112 complexity | 3d178767c393632645a6f163a8ba2d36 MD5 | raw file
  1. /**
  2. * Copyright 2013 Netflix, Inc.
  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.netflix.astyanax.model;
  17. import java.math.BigInteger;
  18. import java.nio.ByteBuffer;
  19. import java.nio.charset.CharacterCodingException;
  20. import java.util.AbstractList;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.Collection;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.logging.Logger;
  28. import com.netflix.astyanax.shaded.org.apache.cassandra.utils.ByteBufferUtil;
  29. import com.google.common.collect.BiMap;
  30. import com.google.common.collect.ImmutableBiMap;
  31. import com.google.common.collect.ImmutableClassToInstanceMap;
  32. import com.netflix.astyanax.Serializer;
  33. import com.netflix.astyanax.serializers.AsciiSerializer;
  34. import com.netflix.astyanax.serializers.BigIntegerSerializer;
  35. import com.netflix.astyanax.serializers.BooleanSerializer;
  36. import com.netflix.astyanax.serializers.ByteBufferOutputStream;
  37. import com.netflix.astyanax.serializers.ByteBufferSerializer;
  38. import com.netflix.astyanax.serializers.ComparatorType;
  39. import com.netflix.astyanax.serializers.IntegerSerializer;
  40. import com.netflix.astyanax.serializers.LongSerializer;
  41. import com.netflix.astyanax.serializers.SerializerTypeInferer;
  42. import com.netflix.astyanax.serializers.StringSerializer;
  43. import com.netflix.astyanax.serializers.UUIDSerializer;
  44. /**
  45. * Parent class of Composite and DynamicComposite. Acts as a list of objects
  46. * that get serialized into a composite column name. Unless
  47. * setAutoDeserialize(true) is called, it's going to try to match serializers to
  48. * Cassandra comparator types.
  49. *
  50. * @author edanuff
  51. */
  52. @SuppressWarnings("rawtypes")
  53. public abstract class AbstractComposite extends AbstractList<Object> implements Comparable<AbstractComposite> {
  54. public enum ComponentEquality {
  55. LESS_THAN_EQUAL((byte) -1), EQUAL((byte) 0), GREATER_THAN_EQUAL((byte) 1);
  56. private final byte equality;
  57. ComponentEquality(byte equality) {
  58. this.equality = equality;
  59. }
  60. public byte toByte() {
  61. return equality;
  62. }
  63. public static ComponentEquality fromByte(byte equality) {
  64. if (equality > 0) {
  65. return GREATER_THAN_EQUAL;
  66. }
  67. if (equality < 0) {
  68. return LESS_THAN_EQUAL;
  69. }
  70. return EQUAL;
  71. }
  72. }
  73. static final Logger logger = Logger.getLogger(AbstractComposite.class.getName());
  74. public static final BiMap<Class<? extends Serializer>, String> DEFAULT_SERIALIZER_TO_COMPARATOR_MAPPING = new ImmutableBiMap.Builder<Class<? extends Serializer>, String>()
  75. .put(IntegerSerializer.class, IntegerSerializer.get().getComparatorType().getTypeName())
  76. .put(BooleanSerializer.class, BooleanSerializer.get().getComparatorType().getTypeName())
  77. .put(AsciiSerializer.class, AsciiSerializer.get().getComparatorType().getTypeName())
  78. .put(BigIntegerSerializer.class, BigIntegerSerializer.get().getComparatorType().getTypeName())
  79. .put(ByteBufferSerializer.class, ByteBufferSerializer.get().getComparatorType().getTypeName())
  80. .put(LongSerializer.class, LongSerializer.get().getComparatorType().getTypeName())
  81. .put(StringSerializer.class, StringSerializer.get().getComparatorType().getTypeName())
  82. .put(UUIDSerializer.class, UUIDSerializer.get().getComparatorType().getTypeName()).build();
  83. static final ImmutableClassToInstanceMap<Serializer> SERIALIZERS = new ImmutableClassToInstanceMap.Builder<Serializer>()
  84. .put(IntegerSerializer.class, IntegerSerializer.get())
  85. .put(BooleanSerializer.class, BooleanSerializer.get())
  86. .put(AsciiSerializer.class, AsciiSerializer.get())
  87. .put(BigIntegerSerializer.class, BigIntegerSerializer.get())
  88. .put(ByteBufferSerializer.class, ByteBufferSerializer.get())
  89. .put(LongSerializer.class, LongSerializer.get())
  90. .put(StringSerializer.class, StringSerializer.get())
  91. .put(UUIDSerializer.class, UUIDSerializer.get()).build();
  92. public static final BiMap<Byte, String> DEFAULT_ALIAS_TO_COMPARATOR_MAPPING = new ImmutableBiMap.Builder<Byte, String>()
  93. .put((byte) 'a', ComparatorType.ASCIITYPE.getTypeName())
  94. .put((byte) 'b', ComparatorType.BYTESTYPE.getTypeName())
  95. .put((byte) 'i', ComparatorType.INTEGERTYPE.getTypeName())
  96. .put((byte) 'x', ComparatorType.LEXICALUUIDTYPE.getTypeName())
  97. .put((byte) 'l', ComparatorType.LONGTYPE.getTypeName())
  98. .put((byte) 't', ComparatorType.TIMEUUIDTYPE.getTypeName())
  99. .put((byte) 's', ComparatorType.UTF8TYPE.getTypeName())
  100. .put((byte) 'u', ComparatorType.UUIDTYPE.getTypeName()).build();
  101. BiMap<Class<? extends Serializer>, String> serializerToComparatorMapping = DEFAULT_SERIALIZER_TO_COMPARATOR_MAPPING;
  102. BiMap<Byte, String> aliasToComparatorMapping = DEFAULT_ALIAS_TO_COMPARATOR_MAPPING;
  103. final boolean dynamic;
  104. List<Serializer<?>> serializersByPosition = null;
  105. List<String> comparatorsByPosition = null;
  106. public class Component<T> {
  107. final Serializer<T> serializer;
  108. final T value;
  109. final ByteBuffer bytes;
  110. final String comparator;
  111. final ComponentEquality equality;
  112. public Component(T value, ByteBuffer bytes, Serializer<T> serializer, String comparator,
  113. ComponentEquality equality) {
  114. this.serializer = serializer;
  115. this.value = value;
  116. this.bytes = bytes;
  117. this.comparator = comparator;
  118. this.equality = equality;
  119. }
  120. public Serializer<T> getSerializer() {
  121. return serializer;
  122. }
  123. @SuppressWarnings("unchecked")
  124. public <A> A getValue(Serializer<A> s) {
  125. if (s == null) {
  126. s = (Serializer<A>) serializer;
  127. }
  128. if ((value == null) && (bytes != null) && (s != null)) {
  129. ByteBuffer cb = bytes.duplicate();
  130. if (cb.hasRemaining()) {
  131. return s.fromByteBuffer(cb);
  132. }
  133. }
  134. if (value instanceof ByteBuffer) {
  135. return (A) ((ByteBuffer) value).duplicate();
  136. }
  137. return (A) value;
  138. }
  139. public T getValue() {
  140. return getValue(serializer);
  141. }
  142. @SuppressWarnings("unchecked")
  143. public <A> ByteBuffer getBytes(Serializer<A> s) {
  144. if (bytes == null) {
  145. if (value instanceof ByteBuffer) {
  146. return ((ByteBuffer) value).duplicate();
  147. }
  148. if (value == null) {
  149. return null;
  150. }
  151. if (s == null) {
  152. s = (Serializer<A>) serializer;
  153. }
  154. if (s != null) {
  155. return s.toByteBuffer((A) value).duplicate();
  156. }
  157. }
  158. return bytes.duplicate();
  159. }
  160. public ByteBuffer getBytes() {
  161. return getBytes(serializer);
  162. }
  163. public String getComparator() {
  164. return comparator;
  165. }
  166. public ComponentEquality getEquality() {
  167. return equality;
  168. }
  169. @Override
  170. public String toString() {
  171. return "Component [" + getValue() + "]";
  172. }
  173. }
  174. List<Component<?>> components = new ArrayList<Component<?>>();
  175. ByteBuffer serialized = null;
  176. public AbstractComposite(boolean dynamic) {
  177. this.dynamic = dynamic;
  178. }
  179. public AbstractComposite(boolean dynamic, Object... o) {
  180. this.dynamic = dynamic;
  181. this.addAll(Arrays.asList(o));
  182. }
  183. public AbstractComposite(boolean dynamic, List<?> l) {
  184. this.dynamic = dynamic;
  185. this.addAll(l);
  186. }
  187. public List<Component<?>> getComponents() {
  188. return components;
  189. }
  190. public void setComponents(List<Component<?>> components) {
  191. serialized = null;
  192. this.components = components;
  193. }
  194. public Map<Class<? extends Serializer>, String> getSerializerToComparatorMapping() {
  195. return serializerToComparatorMapping;
  196. }
  197. public void setSerializerToComparatorMapping(Map<Class<? extends Serializer>, String> serializerToComparatorMapping) {
  198. serialized = null;
  199. this.serializerToComparatorMapping = new ImmutableBiMap.Builder<Class<? extends Serializer>, String>().putAll(
  200. serializerToComparatorMapping).build();
  201. }
  202. public Map<Byte, String> getAliasesToComparatorMapping() {
  203. return aliasToComparatorMapping;
  204. }
  205. public void setAliasesToComparatorMapping(Map<Byte, String> aliasesToComparatorMapping) {
  206. serialized = null;
  207. aliasToComparatorMapping = new ImmutableBiMap.Builder<Byte, String>().putAll(aliasesToComparatorMapping)
  208. .build();
  209. }
  210. public boolean isDynamic() {
  211. return dynamic;
  212. }
  213. public List<Serializer<?>> getSerializersByPosition() {
  214. return serializersByPosition;
  215. }
  216. public void setSerializersByPosition(List<Serializer<?>> serializersByPosition) {
  217. this.serializersByPosition = serializersByPosition;
  218. }
  219. public void setSerializersByPosition(Serializer<?>... serializers) {
  220. serializersByPosition = Arrays.asList(serializers);
  221. }
  222. public void setSerializerByPosition(int index, Serializer<?> s) {
  223. if (serializersByPosition == null) {
  224. serializersByPosition = new ArrayList<Serializer<?>>();
  225. }
  226. while (serializersByPosition.size() <= index) {
  227. serializersByPosition.add(null);
  228. }
  229. serializersByPosition.set(index, s);
  230. }
  231. public List<String> getComparatorsByPosition() {
  232. return comparatorsByPosition;
  233. }
  234. public void setComparatorsByPosition(List<String> comparatorsByPosition) {
  235. this.comparatorsByPosition = comparatorsByPosition;
  236. }
  237. public void setComparatorsByPosition(String... comparators) {
  238. comparatorsByPosition = Arrays.asList(comparators);
  239. }
  240. public void setComparatorByPosition(int index, String c) {
  241. if (comparatorsByPosition == null) {
  242. comparatorsByPosition = new ArrayList<String>();
  243. }
  244. while (comparatorsByPosition.size() <= index) {
  245. comparatorsByPosition.add(null);
  246. }
  247. comparatorsByPosition.set(index, c);
  248. }
  249. @Override
  250. public int compareTo(AbstractComposite o) {
  251. return serialize().compareTo(o.serialize());
  252. }
  253. private String comparatorForSerializer(Serializer<?> s) {
  254. String comparator = serializerToComparatorMapping.get(s.getClass());
  255. if (comparator != null) {
  256. return comparator;
  257. }
  258. return ComparatorType.BYTESTYPE.getTypeName();
  259. }
  260. private Serializer<?> serializerForComparator(String c) {
  261. int p = c.indexOf('(');
  262. if (p >= 0) {
  263. c = c.substring(0, p);
  264. }
  265. if (ComparatorType.LEXICALUUIDTYPE.getTypeName().equals(c)
  266. || ComparatorType.TIMEUUIDTYPE.getTypeName().equals(c)) {
  267. return UUIDSerializer.get();
  268. }
  269. Serializer<?> s = SERIALIZERS.getInstance(serializerToComparatorMapping.inverse().get(c));
  270. if (s != null) {
  271. return s;
  272. }
  273. return ByteBufferSerializer.get();
  274. }
  275. private Serializer<?> serializerForPosition(int i) {
  276. if (serializersByPosition == null) {
  277. return null;
  278. }
  279. if (i >= serializersByPosition.size()) {
  280. return null;
  281. }
  282. return serializersByPosition.get(i);
  283. }
  284. private Serializer<?> getSerializer(int i, String c) {
  285. Serializer<?> s = serializerForPosition(i);
  286. if (s != null) {
  287. return s;
  288. }
  289. return serializerForComparator(c);
  290. }
  291. private String comparatorForPosition(int i) {
  292. if (comparatorsByPosition == null) {
  293. return null;
  294. }
  295. if (i >= comparatorsByPosition.size()) {
  296. return null;
  297. }
  298. return comparatorsByPosition.get(i);
  299. }
  300. private String getComparator(int i, ByteBuffer bb) {
  301. String name = comparatorForPosition(i);
  302. if (name != null) {
  303. return name;
  304. }
  305. if (!dynamic) {
  306. if (bb.hasRemaining()) {
  307. return ComparatorType.BYTESTYPE.getTypeName();
  308. }
  309. else {
  310. return null;
  311. }
  312. }
  313. if (bb.hasRemaining()) {
  314. try {
  315. int header = getShortLength(bb);
  316. if ((header & 0x8000) == 0) {
  317. name = ByteBufferUtil.string(getBytes(bb, header));
  318. }
  319. else {
  320. byte a = (byte) (header & 0xFF);
  321. name = aliasToComparatorMapping.get(a);
  322. if (name == null) {
  323. a = (byte) Character.toLowerCase((char) a);
  324. name = aliasToComparatorMapping.get(a);
  325. if (name != null) {
  326. name += "(reversed=true)";
  327. }
  328. }
  329. }
  330. }
  331. catch (CharacterCodingException e) {
  332. throw new RuntimeException(e);
  333. }
  334. }
  335. if ((name != null) && (name.length() == 0)) {
  336. name = null;
  337. }
  338. return name;
  339. }
  340. @Override
  341. public void clear() {
  342. serialized = null;
  343. components = new ArrayList<Component<?>>();
  344. }
  345. @Override
  346. public int size() {
  347. return components.size();
  348. }
  349. public <T> AbstractComposite addComponent(T value, Serializer<T> s) {
  350. addComponent(value, s, comparatorForSerializer(s));
  351. return this;
  352. }
  353. public <T> AbstractComposite addComponent(T value, Serializer<T> s, ComponentEquality equality) {
  354. addComponent(value, s, comparatorForSerializer(s), equality);
  355. return this;
  356. }
  357. public <T> AbstractComposite addComponent(T value, Serializer<T> s, String comparator) {
  358. addComponent(value, s, comparator, ComponentEquality.EQUAL);
  359. return this;
  360. }
  361. public <T> AbstractComposite addComponent(T value, Serializer<T> s, String comparator, ComponentEquality equality) {
  362. addComponent(-1, value, s, comparator, equality);
  363. return this;
  364. }
  365. @SuppressWarnings("unchecked")
  366. public <T> AbstractComposite addComponent(int index, T value, Serializer<T> s, String comparator,
  367. ComponentEquality equality) {
  368. serialized = null;
  369. if (index < 0) {
  370. index = components.size();
  371. }
  372. while (components.size() < index) {
  373. components.add(null);
  374. }
  375. components.add(index, new Component(value, null, s, comparator, equality));
  376. return this;
  377. }
  378. private static Object mapIfNumber(Object o) {
  379. if ((o instanceof Byte) || (o instanceof Integer) || (o instanceof Short)) {
  380. return BigInteger.valueOf(((Number) o).longValue());
  381. }
  382. return o;
  383. }
  384. @SuppressWarnings({ "unchecked" })
  385. private static Collection<?> flatten(Collection<?> c) {
  386. if (c instanceof AbstractComposite) {
  387. return ((AbstractComposite) c).getComponents();
  388. }
  389. boolean hasCollection = false;
  390. for (Object o : c) {
  391. if (o instanceof Collection) {
  392. hasCollection = true;
  393. break;
  394. }
  395. }
  396. if (!hasCollection) {
  397. return c;
  398. }
  399. List newList = new ArrayList();
  400. for (Object o : c) {
  401. if (o instanceof Collection) {
  402. newList.addAll(flatten((Collection) o));
  403. }
  404. else {
  405. newList.add(o);
  406. }
  407. }
  408. return newList;
  409. }
  410. @Override
  411. public boolean addAll(Collection<? extends Object> c) {
  412. return super.addAll(flatten(c));
  413. }
  414. @Override
  415. public boolean containsAll(Collection<?> c) {
  416. return super.containsAll(flatten(c));
  417. }
  418. @Override
  419. public boolean removeAll(Collection<?> c) {
  420. return super.removeAll(flatten(c));
  421. }
  422. @Override
  423. public boolean retainAll(Collection<?> c) {
  424. return super.retainAll(flatten(c));
  425. }
  426. @Override
  427. public boolean addAll(int i, Collection<? extends Object> c) {
  428. return super.addAll(i, flatten(c));
  429. }
  430. @SuppressWarnings("unchecked")
  431. @Override
  432. public void add(int index, Object element) {
  433. serialized = null;
  434. if (element instanceof Component) {
  435. components.add(index, (Component<?>) element);
  436. return;
  437. }
  438. element = mapIfNumber(element);
  439. Serializer s = serializerForPosition(index);
  440. if (s == null) {
  441. s = SerializerTypeInferer.getSerializer(element);
  442. }
  443. String c = comparatorForPosition(index);
  444. if (c == null) {
  445. c = comparatorForSerializer(s);
  446. }
  447. components.add(index, new Component(element, null, s, c, ComponentEquality.EQUAL));
  448. }
  449. @Override
  450. public Object remove(int index) {
  451. serialized = null;
  452. Component prev = components.remove(index);
  453. if (prev != null) {
  454. return prev.getValue();
  455. }
  456. return null;
  457. }
  458. public <T> AbstractComposite setComponent(int index, T value, Serializer<T> s) {
  459. setComponent(index, value, s, comparatorForSerializer(s));
  460. return this;
  461. }
  462. public <T> AbstractComposite setComponent(int index, T value, Serializer<T> s, String comparator) {
  463. setComponent(index, value, s, comparator, ComponentEquality.EQUAL);
  464. return this;
  465. }
  466. @SuppressWarnings("unchecked")
  467. public <T> AbstractComposite setComponent(int index, T value, Serializer<T> s, String comparator,
  468. ComponentEquality equality) {
  469. serialized = null;
  470. while (components.size() <= index) {
  471. components.add(null);
  472. }
  473. components.set(index, new Component(value, null, s, comparator, equality));
  474. return this;
  475. }
  476. @SuppressWarnings("unchecked")
  477. @Override
  478. public Object set(int index, Object element) {
  479. serialized = null;
  480. if (element instanceof Component) {
  481. Component prev = components.set(index, (Component<?>) element);
  482. if (prev != null) {
  483. return prev.getValue();
  484. }
  485. return null;
  486. }
  487. element = mapIfNumber(element);
  488. Serializer s = serializerForPosition(index);
  489. if (s == null) {
  490. s = SerializerTypeInferer.getSerializer(element);
  491. }
  492. String c = comparatorForPosition(index);
  493. if (c == null) {
  494. c = comparatorForSerializer(s);
  495. }
  496. Component prev = components.set(index, new Component(element, null, s, c, ComponentEquality.EQUAL));
  497. if (prev != null) {
  498. return prev.getValue();
  499. }
  500. return null;
  501. }
  502. @Override
  503. public Object get(int i) {
  504. Component c = components.get(i);
  505. if (c != null) {
  506. return c.getValue();
  507. }
  508. return null;
  509. }
  510. public <T> T get(int i, Serializer<T> s) throws ClassCastException {
  511. T value = null;
  512. Component<?> c = components.get(i);
  513. if (c != null) {
  514. value = c.getValue(s);
  515. }
  516. return value;
  517. }
  518. public Component getComponent(int i) {
  519. if (i >= components.size()) {
  520. return null;
  521. }
  522. Component c = components.get(i);
  523. return c;
  524. }
  525. public Iterator<Component<?>> componentsIterator() {
  526. return components.iterator();
  527. }
  528. @SuppressWarnings("unchecked")
  529. public ByteBuffer serialize() {
  530. if (serialized != null) {
  531. return serialized.duplicate();
  532. }
  533. ByteBufferOutputStream out = new ByteBufferOutputStream();
  534. int i = 0;
  535. for (Component c : components) {
  536. Serializer<?> s = serializerForPosition(i);
  537. ByteBuffer cb = c.getBytes(s);
  538. if (cb == null) {
  539. cb = ByteBuffer.allocate(0);
  540. }
  541. if (dynamic) {
  542. String comparator = comparatorForPosition(i);
  543. if (comparator == null) {
  544. comparator = c.getComparator();
  545. }
  546. if (comparator == null) {
  547. comparator = ComparatorType.BYTESTYPE.getTypeName();
  548. }
  549. int p = comparator.indexOf("(reversed=true)");
  550. boolean desc = false;
  551. if (p >= 0) {
  552. comparator = comparator.substring(0, p);
  553. desc = true;
  554. }
  555. if (aliasToComparatorMapping.inverse().containsKey(comparator)) {
  556. byte a = aliasToComparatorMapping.inverse().get(comparator);
  557. if (desc) {
  558. a = (byte) Character.toUpperCase((char) a);
  559. }
  560. out.writeShort((short) (0x8000 | a));
  561. }
  562. else {
  563. out.writeShort((short) comparator.length());
  564. out.write(ByteBufferUtil.bytes(comparator));
  565. }
  566. }
  567. out.writeShort((short) cb.remaining());
  568. out.write(cb.slice());
  569. out.write(c.getEquality().toByte());
  570. i++;
  571. }
  572. serialized = out.getByteBuffer();
  573. return serialized.duplicate();
  574. }
  575. @SuppressWarnings("unchecked")
  576. public void deserialize(ByteBuffer b) {
  577. serialized = b.duplicate();
  578. components = new ArrayList<Component<?>>();
  579. String comparator = null;
  580. int i = 0;
  581. while ((comparator = getComparator(i, b)) != null) {
  582. ByteBuffer data = getWithShortLength(b);
  583. if (data != null) {
  584. Serializer<?> s = getSerializer(i, comparator);
  585. ComponentEquality equality = ComponentEquality.fromByte(b.get());
  586. components.add(new Component(null, data.slice(), s, comparator, equality));
  587. }
  588. else {
  589. throw new RuntimeException("Missing component data in composite type");
  590. }
  591. i++;
  592. }
  593. }
  594. protected static int getShortLength(ByteBuffer bb) {
  595. int length = (bb.get() & 0xFF) << 8;
  596. return length | (bb.get() & 0xFF);
  597. }
  598. protected static ByteBuffer getBytes(ByteBuffer bb, int length) {
  599. ByteBuffer copy = bb.duplicate();
  600. copy.limit(copy.position() + length);
  601. bb.position(bb.position() + length);
  602. return copy;
  603. }
  604. protected static ByteBuffer getWithShortLength(ByteBuffer bb) {
  605. int length = getShortLength(bb);
  606. return getBytes(bb, length);
  607. }
  608. }