Package com.elasticinbox.core.cassandra.persistence

Source Code of com.elasticinbox.core.cassandra.persistence.Marshaller

/**
* Copyright (c) 2011-2014 Optimax Software Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*  * Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*  * Neither the name of Optimax Software, ElasticInbox, nor the names
*    of its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.elasticinbox.core.cassandra.persistence;

import static me.prettyprint.hector.api.factory.HFactory.createColumn;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import me.prettyprint.cassandra.serializers.BytesArraySerializer;
import me.prettyprint.cassandra.serializers.DateSerializer;
import me.prettyprint.cassandra.serializers.LongSerializer;
import me.prettyprint.cassandra.serializers.SerializerTypeInferer;
import me.prettyprint.cassandra.serializers.StringSerializer;
import me.prettyprint.hector.api.beans.HColumn;

import com.elasticinbox.common.utils.IOUtils;
import com.elasticinbox.common.utils.JSONUtils;
import com.elasticinbox.config.Configurator;
import com.elasticinbox.core.model.Address;
import com.elasticinbox.core.model.AddressList;
import com.elasticinbox.core.model.Marker;
import com.elasticinbox.core.model.Message;
import com.elasticinbox.core.model.MimePart;

public final class Marshaller
{
  public final static String CN_DATE = "date";
  public final static String CN_SIZE = "size";
  public final static String CN_FROM = "from";
  public final static String CN_TO = "to";
  public final static String CN_CC = "cc";
  public final static String CN_BCC = "bcc";
  public final static String CN_REPLY_TO = "replyto";
  public final static String CN_MESSAGE_ID = "mid";
  public final static String CN_SUBJECT = "subject";
  public final static String CN_HTML_BODY = "html";
  public final static String CN_PLAIN_BODY = "plain";
  public final static String CN_PARTS = "parts";
  public final static String CN_BRI = "bri"; // Blob Resource Identifier
  public final static String CN_LABEL_PREFIX = "l:";
  public final static String CN_MARKER_PREFIX = "m:";

  private final static DateSerializer dateSe = DateSerializer.get();
  private final static LongSerializer longSe = LongSerializer.get();
  private final static StringSerializer strSe = StringSerializer.get();
  private final static BytesArraySerializer byteSe = BytesArraySerializer.get();

  /**
   * Unmarshall message contents from Cassandra {@link HColumn} columns and
   * return resulting {@link Message} object.
   *
   * @param columns
   *            Cassandra columns to unmarshall
   * @param includeBody
   *            Contents of the message body (plain and HTML) will not be
   *            included in the result if set to false
   * @return
   */
  protected static Message unmarshall(
      final List<HColumn<String, byte[]>> columns,
      final boolean includeBody)
  {
    Message message = new Message();

    for (HColumn<String, byte[]> c : columns)
    {
      if (c != null && c.getValue() != null)
      {
        // map columns to Message object
        if (c.getName().equals(CN_DATE)) {
          message.setDate(dateSe.fromBytes(c.getValue()));
        } else if (c.getName().equals(CN_SIZE)) {
          message.setSize(longSe.fromBytes(c.getValue()));
        } else if (c.getName().equals(CN_SUBJECT)) {
          message.setSubject(strSe.fromBytes(c.getValue()));
        } else if (c.getName().equals(CN_MESSAGE_ID)) {
          message.setMessageId(strSe.fromBytes(c.getValue()));
        } else if (c.getName().equals(CN_FROM)) {
          message.setFrom(unserializeAddress(c.getValue()));
        } else if (c.getName().equals(CN_TO)) {
          message.setTo(unserializeAddress(c.getValue()));
        } else if (c.getName().equals(CN_CC)) {
          message.setCc(unserializeAddress(c.getValue()));
        } else if (c.getName().equals(CN_BCC)) {
          message.setBcc(unserializeAddress(c.getValue()));
        } else if (c.getName().equals(CN_REPLY_TO)) {
          message.setReplyTo(unserializeAddress(c.getValue()));
        } else if (c.getName().equals(CN_BRI)) {
          message.setLocation(URI.create(
              strSe.fromBytes(c.getValue())));
        } else if (c.getName().startsWith(CN_LABEL_PREFIX)) {
          Integer labelId = Integer
              .parseInt(c.getName().split("\\:")[1]);
          message.addLabel(labelId);
        } else if (c.getName().startsWith(CN_MARKER_PREFIX)) {
          Integer markerId = Integer
              .parseInt(c.getName().split("\\:")[1]);
          message.addMarker(Marker.fromInt(markerId));
        } else if (includeBody && c.getName().equals(CN_HTML_BODY)) {
          try {
            message.setHtmlBody(strSe.fromBytes(
                IOUtils.decompress(c.getValue())));
          } catch (Exception e) {
            //TODO: logger.error("Decompression of message body failed: ", e);
          }
        } else if (includeBody && c.getName().equals(CN_PLAIN_BODY)) {
          try {
            message.setPlainBody(strSe.fromBytes(
                IOUtils.decompress(c.getValue())));
          } catch (Exception e) {
            //TODO: logger.error("Decompression of message body failed: ", e);
          }
        } else if (c.getName().equals(CN_PARTS)) {
          Map<String, MimePart> parts = null;
          parts = JSONUtils.toObject(c.getValue(), parts);
          message.setParts(parts);
            }
      }
    }

    return message;
  }

  /**
   * Marshall the {@link Message} object contents to Cassandra columns
   *
   * @param m Message to marshall
   * @return
   * @throws IOException
   */
  protected static List<HColumn<String, byte[]>> marshall(final Message m)
      throws IOException
  {
    Map<String, Object> columns = new HashMap<String, Object>();

    if (m.getSize() != null) {
      columns.put(CN_SIZE, m.getSize());
    }

    if (m.getDate() != null) {
      columns.put(CN_DATE, m.getDate());
    }

    if (m.getFrom() != null) {
      columns.put(CN_FROM, serializeAddress(m.getFrom()));
    }

    if (m.getTo() != null) {
      columns.put(CN_TO, serializeAddress(m.getTo()));
    }

    if (m.getCc() != null) {
      columns.put(CN_CC, serializeAddress(m.getCc()));
    }

    if (m.getBcc() != null) {
      columns.put(CN_BCC, serializeAddress(m.getBcc()));
    }

    if (m.getReplyTo() != null) {
      columns.put(CN_REPLY_TO, serializeAddress(m.getReplyTo()));
    }

    if (m.getMessageId() != null) {
      columns.put(CN_MESSAGE_ID, m.getMessageId());
    }

    if (m.getSubject() != null) {
      columns.put(CN_SUBJECT, m.getSubject());
    }

    if (m.getLocation() != null) {
      columns.put(CN_BRI, m.getLocation().toString());
    }

    if (m.getParts() != null) {
      columns.put(CN_PARTS, JSONUtils.fromObject(m.getParts()));
    }

    // add markers
    if (!m.getMarkers().isEmpty())
    {
      for (Marker marker : m.getMarkers())
      {
        String cn = CN_MARKER_PREFIX + marker.toInt();
        columns.put(cn, new byte[0]);
      }
    }

    // add labels
    if (!m.getLabels().isEmpty())
    {
      for (Integer labelId : m.getLabels())
      {
        String cn = CN_LABEL_PREFIX + labelId;
        columns.put(cn, new byte[0]);
      }
    }

    // add HTML message text
    // Fallback: if HTML is enabled but not available, store PLAIN message text
    if (Configurator.isStoreHtmlWithMetadata())
    {
      if (m.getHtmlBody() != null) {
        columns.put(CN_HTML_BODY, IOUtils.compress(m.getHtmlBody()));
      } else if (!Configurator.isStorePlainWithMetadata() && (m.getPlainBody() != null)) {
        columns.put(CN_PLAIN_BODY, IOUtils.compress(m.getPlainBody()));
      }
    }

    // add PLAIN message text
    if (Configurator.isStorePlainWithMetadata() && (m.getPlainBody() != null)) {
      columns.put(CN_PLAIN_BODY, IOUtils.compress(m.getPlainBody()));
    }

    return mapToHColumns(columns);
  }

  /**
   * Serialize {@link AddressList} to JSON
   *
   * @param addresses
   * @return
   */
  private static byte[] serializeAddress(final AddressList addresses)
  {
    List<String[]> result = new ArrayList<String[]>();

    for (Address address : addresses)
    {
      result.add(new String[]{
          (address.getName() == null ? "" : address.getName()),
          (address.getAddress() == null ? "" : address.getAddress()) });
    }

    return JSONUtils.fromObject(result);
  }

  /**
   * Unserialize JSON sting to {@link AddressList}
   *
   * @param val
   * @return
   */
  private static AddressList unserializeAddress(final byte[] val)
  {
    List<Address> result = new ArrayList<Address>();

    List<List<String>> addresses = null;
    addresses = JSONUtils.toObject(val, addresses);

    for (List<String> address : addresses) {
      result.add(new Address(address.get(0), address.get(1)));
    }

    return new AddressList(result);
  }

  /**
   * Convert Map of arbitrary Objects to the List of HColumns serialized as
   * <code>byte[]</code>
   *
   * @param map
   * @return
   */
  protected static List<HColumn<String, byte[]>> mapToHColumns(
      final Map<String, Object> map)
  {
    List<HColumn<String, byte[]>> columns =
      new ArrayList<HColumn<String, byte[]>>(map.size());

    for (Map.Entry<String, Object> a : map.entrySet())
    {
      columns.add(createColumn(a.getKey(), SerializerTypeInferer
          .getSerializer(a.getValue()).toBytes(a.getValue()),
          strSe, byteSe));
    }
   
    return columns;
  }
}
TOP

Related Classes of com.elasticinbox.core.cassandra.persistence.Marshaller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.