Package com.orientechnologies.orient.core.serialization.serializer.record.string

Source Code of com.orientechnologies.orient.core.serialization.serializer.record.string.ORecordSerializerStringAbstract

/*
* Copyright 1999-2010 Luca Garulli (l.garulli--at--orientechnologies.com)
*
* Licensed 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 com.orientechnologies.orient.core.serialization.serializer.record.string;

import java.util.Calendar;
import java.util.Date;
import java.util.Set;

import com.orientechnologies.common.profiler.OProfiler;
import com.orientechnologies.orient.core.db.ODatabaseComplex;
import com.orientechnologies.orient.core.db.OUserObject2RecordHandler;
import com.orientechnologies.orient.core.db.record.ODatabaseRecord;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.ORecordInternal;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.serialization.OBase64Utils;
import com.orientechnologies.orient.core.serialization.OBinaryProtocol;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.core.serialization.serializer.record.ORecordSerializer;
import com.orientechnologies.orient.core.serialization.serializer.record.OSerializationThreadLocal;
import com.orientechnologies.orient.core.serialization.serializer.string.OStringSerializerAnyStreamable;

public abstract class ORecordSerializerStringAbstract implements ORecordSerializer {
  private static final char    DECIMAL_SEPARATOR      = '.';
  private static final String  MAX_INTEGER_AS_STRING  = String.valueOf(Integer.MAX_VALUE);
  private static final int    MAX_INTEGER_DIGITS    = MAX_INTEGER_AS_STRING.length();

  protected abstract StringBuilder toString(final ORecordInternal<?> iRecord, final StringBuilder iOutput, final String iFormat,
      final OUserObject2RecordHandler iObjHandler, final Set<Integer> iMarshalledRecords, boolean iOnlyDelta);

  protected abstract ORecordInternal<?> fromString(final ODatabaseRecord iDatabase, final String iContent,
      final ORecordInternal<?> iRecord);

  public StringBuilder toString(final ORecordInternal<?> iRecord, final String iFormat) {
    return toString(iRecord, new StringBuilder(), iFormat, iRecord.getDatabase(), OSerializationThreadLocal.INSTANCE.get(), false);
  }

  public StringBuilder toString(final ORecordInternal<?> iRecord, final StringBuilder iOutput, final String iFormat) {
    return toString(iRecord, iOutput, iFormat, iRecord.getDatabase(), OSerializationThreadLocal.INSTANCE.get(), false);
  }

  public ORecordInternal<?> fromString(final ODatabaseRecord iDatabase, final String iSource) {
    return fromString(iDatabase, iSource, (ORecordInternal<?>) iDatabase.newInstance());
  }

  public ORecordInternal<?> fromStream(final ODatabaseRecord iDatabase, final byte[] iSource, final ORecordInternal<?> iRecord) {
    final long timer = OProfiler.getInstance().startChrono();

    try {
      return fromString(iDatabase, OBinaryProtocol.bytes2string(iSource), iRecord);
    } finally {

      OProfiler.getInstance().stopChrono("ORecordSerializerStringAbstract.fromStream", timer);
    }
  }

  public byte[] toStream(final ODatabaseRecord iDatabase, final ORecordInternal<?> iRecord, boolean iOnlyDelta) {
    final long timer = OProfiler.getInstance().startChrono();

    try {
      return OBinaryProtocol.string2bytes(toString(iRecord, new StringBuilder(), null, iDatabase,
          OSerializationThreadLocal.INSTANCE.get(), iOnlyDelta).toString());
    } finally {

      OProfiler.getInstance().stopChrono("ORecordSerializerStringAbstract.toStream", timer);
    }
  }

  public static Object fieldTypeFromStream(final ODocument iDocument, OType iType, final Object iValue) {
    if (iValue == null)
      return null;

    if (iType == null)
      iType = OType.EMBEDDED;

    switch (iType) {
    case STRING:
      if (iValue instanceof String) {
        final String s = (String) iValue;
        return OStringSerializerHelper.decode(s.substring(1, s.length() - 1));
      }
      return iValue.toString();

    case INTEGER:
      if (iValue instanceof Integer)
        return iValue;
      return new Integer(iValue.toString());

    case BOOLEAN:
      if (iValue instanceof Boolean)
        return iValue;
      return new Boolean(iValue.toString());

    case FLOAT:
      if (iValue instanceof Float)
        return iValue;
      return convertValue((String) iValue, iType);

    case LONG:
      if (iValue instanceof Long)
        return iValue;
      return convertValue((String) iValue, iType);

    case DOUBLE:
      if (iValue instanceof Double)
        return iValue;
      return convertValue((String) iValue, iType);

    case SHORT:
      if (iValue instanceof Short)
        return iValue;
      return convertValue((String) iValue, iType);

    case BYTE:
      if (iValue instanceof Byte)
        return iValue;
      return convertValue((String) iValue, iType);

    case BINARY:
      if (iValue instanceof byte[])
        return iValue;
      if (iValue instanceof String) {
        final String s = (String) iValue;
        if (s.length() > 2)
          return OBase64Utils.decode(s.substring(1, s.length() - 1));
        return null;
      }

    case DATE:
    case DATETIME:
      if (iValue instanceof Date)
        return iValue;
      return convertValue((String) iValue, iType);

    case LINK:
      if (iValue instanceof ORID)
        return iValue.toString();
      else if (iValue instanceof String)
        return new ORecordId((String) iValue);
      else
        return ((ORecord<?>) iValue).getIdentity().toString();

    case EMBEDDED:
      // RECORD
      return OStringSerializerAnyStreamable.INSTANCE.fromStream(iDocument.getDatabase(), (String) iValue);

    case EMBEDDEDSET:
    case EMBEDDEDLIST: {
      final String value = (String) iValue;
      return ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedCollectionFromStream(iDocument.getDatabase(), iDocument, iType,
          null, null, value);
    }

    case EMBEDDEDMAP: {
      final String value = (String) iValue;
      return ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedMapFromStream(iDocument, null, value);
    }
    }

    throw new IllegalArgumentException("Type " + iType + " not supported to convert value: " + iValue);
  }

  public static Object convertValue(final String iValue, final OType iExpectedType) {
    final Object v = getTypeValue((String) iValue);
    return OType.convert(v, iExpectedType.getDefaultJavaType());
  }

  public static void fieldTypeToString(final StringBuilder iBuffer, final ODatabaseComplex<?> iDatabase, OType iType,
      final Object iValue) {
    if (iValue == null)
      return;

    final long timer = OProfiler.getInstance().startChrono();

    if (iType == null) {
      if (iValue instanceof ORID)
        iType = OType.LINK;
      else
        iType = OType.EMBEDDED;
    }

    switch (iType) {
    case STRING:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.string2string", timer);
      break;

    case BOOLEAN:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.bool2string", timer);
      break;

    case INTEGER:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.int2string", timer);
      break;

    case FLOAT:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.float2string", timer);
      break;

    case LONG:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.long2string", timer);
      break;

    case DOUBLE:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.double2string", timer);
      break;

    case SHORT:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.short2string", timer);
      break;

    case BYTE:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.byte2string", timer);
      break;

    case BINARY:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.binary2string", timer);
      break;

    case DATE:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.date2string", timer);
      break;

    case DATETIME:
      simpleValueToStream(iBuffer, iType, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.datetime2string", timer);
      break;

    case LINK:
      if (iValue instanceof ORecordId)
        ((ORecordId) iValue).toString(iBuffer);
      else
        ((ORecord<?>) iValue).getIdentity().toString(iBuffer);
      OProfiler.getInstance().stopChrono("serializer.rec.str.link2string", timer);
      break;

    case EMBEDDEDSET:
      ORecordSerializerSchemaAware2CSV.INSTANCE
          .embeddedCollectionToStream(iDatabase, null, iBuffer, null, null, iValue, null, true);
      OProfiler.getInstance().stopChrono("serializer.rec.str.embedSet2string", timer);
      break;

    case EMBEDDEDLIST:
      ORecordSerializerSchemaAware2CSV.INSTANCE
          .embeddedCollectionToStream(iDatabase, null, iBuffer, null, null, iValue, null, true);
      OProfiler.getInstance().stopChrono("serializer.rec.str.embedList2string", timer);
      break;

    case EMBEDDEDMAP:
      ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedMapToStream(iDatabase, null, iBuffer, null, null, iValue, null, true);
      OProfiler.getInstance().stopChrono("serializer.rec.str.embedMap2string", timer);
      break;

    case EMBEDDED:
      // RECORD
      OStringSerializerAnyStreamable.INSTANCE.toStream(iDatabase, iBuffer, iValue);
      OProfiler.getInstance().stopChrono("serializer.rec.str.embed2string", timer);
      break;

    default:
      throw new IllegalArgumentException("Type " + iType + " not supported to convert value: " + iValue);
    }
  }

  /**
   * Parses a string returning the closer type. Numbers by default are INTEGER if haven't decimal separator, otherwise FLOAT. To
   * treat all the number types numbers are postponed with a character that tells the type: b=byte, s=short, l=long, f=float,
   * d=double, t=date.
   *
   * @param iUnusualSymbols
   *          Localized decimal number separators
   * @param iValue
   *          Value to parse
   * @return The closest type recognized
   */
  public static OType getType(final String iValue) {
    if (iValue.length() == 0)
      return null;

    final char firstChar = iValue.charAt(0);

    if (firstChar == ORID.PREFIX)
      // RID
      return OType.LINK;
    else if (firstChar == '\'' || firstChar == '"')
      return OType.STRING;
    else if (firstChar == OStringSerializerHelper.PARENTHESIS_BEGIN)
      return OType.EMBEDDED;
    else if (firstChar == OStringSerializerHelper.LINK)
      return OType.LINK;
    else if (firstChar == OStringSerializerHelper.COLLECTION_BEGIN)
      return OType.EMBEDDEDLIST;
    else if (firstChar == OStringSerializerHelper.MAP_BEGIN)
      return OType.EMBEDDEDMAP;

    // NUMBER OR STRING?
    boolean integer = true;
    for (int index = 0; index < iValue.length(); ++index) {
      final char c = iValue.charAt(index);
      if (c < '0' || c > '9')
        if ((index == 0 && (c == '+' || c == '-')))
          continue;
        else if (c == DECIMAL_SEPARATOR)
          integer = false;
        else {
          if (index > 0)
            if (c == 'f')
              return OType.FLOAT;
            else if (c == 'l')
              return OType.LONG;
            else if (c == 'd')
              return OType.DOUBLE;
            else if (c == 'b')
              return OType.BYTE;
            else if (c == 'a')
              return OType.DATE;
            else if (c == 't')
              return OType.DATETIME;
            else if (c == 's')
              return OType.SHORT;

          return OType.STRING;
        }
    }

    if (integer) {
      // AUTO CONVERT TO LONG IF THE INTEGER IS TOO BIG
      final int numberLength = iValue.length();
      if (numberLength > MAX_INTEGER_DIGITS || (numberLength == MAX_INTEGER_DIGITS && iValue.compareTo(MAX_INTEGER_AS_STRING) > 0))
        return OType.LONG;
    }

    return integer ? OType.INTEGER : OType.FLOAT;
  }

  /**
   * Parses a string returning the value with the closer type. Numbers by default are INTEGER if haven't decimal separator,
   * otherwise FLOAT. To treat all the number types numbers are postponed with a character that tells the type: b=byte, s=short,
   * l=long, f=float, d=double, t=date. If starts with # it's a RecordID. Most of the code is equals to getType() but has been
   * copied to speed-up it.
   *
   * @param iUnusualSymbols
   *          Localized decimal number separators
   * @param iValue
   *          Value to parse
   * @return The closest type recognized
   */
  public static Object getTypeValue(final String iValue) {
    if (iValue == null)
      return null;

    if (iValue.length() > 1 && iValue.charAt(0) == '"' && iValue.charAt(iValue.length() - 1) == '"')
      // STRING
      return iValue.substring(1, iValue.length() - 1);

    if (iValue.charAt(0) == ORID.PREFIX)
      // RID
      return new ORecordId(iValue);

    boolean integer = true;
    char c;

    for (int index = 0; index < iValue.length(); ++index) {
      c = iValue.charAt(index);
      if (c < '0' || c > '9')
        if ((index == 0 && (c == '+' || c == '-')))
          continue;
        else if (c == DECIMAL_SEPARATOR)
          integer = false;
        else {
          if (index > 0) {
            final String v = iValue.substring(0, index);

            if (c == 'f')
              return new Float(v);
            else if (c == 'l')
              return new Long(v);
            else if (c == 'd')
              return new Double(v);
            else if (c == 'b')
              return new Byte(v);
            else if (c == 'a' || c == 't')
              return new Date(Long.parseLong(v));
            else if (c == 's')
              return new Short(v);
          }
          return iValue;
        }
    }

    if (integer)
      return new Integer(iValue);
    else
      return new Float(iValue);
  }

  public static void simpleValueToStream(final StringBuilder iBuffer, final OType iType, final Object iValue) {
    if (iValue == null || iType == null)
      return;
    switch (iType) {
    case STRING:
      iBuffer.append('"');
      iBuffer.append(OStringSerializerHelper.encode(iValue.toString()));
      iBuffer.append('"');
      break;

    case BOOLEAN:
      iBuffer.append(String.valueOf(iValue));
      break;

    case INTEGER:
      iBuffer.append(String.valueOf(iValue));
      break;

    case FLOAT:
      iBuffer.append(String.valueOf(iValue));
      iBuffer.append('f');
      break;

    case LONG:
      iBuffer.append(String.valueOf(iValue));
      iBuffer.append('l');
      break;

    case DOUBLE:
      iBuffer.append(String.valueOf(iValue));
      iBuffer.append('d');
      break;

    case SHORT:
      iBuffer.append(String.valueOf(iValue));
      iBuffer.append('s');
      break;

    case BYTE:
      if (iValue instanceof Character)
        iBuffer.append((int) ((Character) iValue).charValue());
      else if (iValue instanceof String)
        iBuffer.append(String.valueOf((int) ((String) iValue).charAt(0)));
      else
        iBuffer.append(String.valueOf(iValue));
      iBuffer.append('b');
      break;

    case BINARY:
      iBuffer.append('"');
      if (iValue instanceof Byte)
        iBuffer.append(new String(new byte[] { ((Byte) iValue).byteValue() }));
      else
        iBuffer.append(OBase64Utils.encodeBytes((byte[]) iValue));
      iBuffer.append('"');
      break;

    case DATE:
      if (iValue instanceof Date) {
        // RESET HOURS, MINUTES, SECONDS AND MILLISECONDS
        Calendar calendar = Calendar.getInstance();
        calendar.setTime((Date) iValue);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        iBuffer.append(calendar.getTimeInMillis());
      } else
        iBuffer.append(iValue);
      iBuffer.append('a');
      break;

    case DATETIME:
      if (iValue instanceof Date)
        iBuffer.append(((Date) iValue).getTime());
      else
        iBuffer.append(iValue);
      iBuffer.append('t');
      break;
    }
  }
}
TOP

Related Classes of com.orientechnologies.orient.core.serialization.serializer.record.string.ORecordSerializerStringAbstract

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.