All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fakemongo.impl.Util Maven / Gradle / Ivy

package com.github.fakemongo.impl;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.FongoDBCollection;
import com.mongodb.LazyDBList;
import com.mongodb.gridfs.GridFSFile;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.bson.BSON;
import org.bson.LazyBSONObject;
import org.bson.types.Binary;

public final class Util {

  private Util() {
  }

  public static  BasicDBList list(T... ts) {
    return wrap(Arrays.asList(ts));
  }

  /**
   * Can extract field from an object.
   * Handle "field1.field2" in { field1 : {field2 : value2 } }
   *
   * @param object
   * @param field
   * @return null if not found.
   */
  public static  T extractField(DBObject object, String field) {
    if (object == null) {
      return null; // NPE ?
    }
    T value;
    int indexDot = field.indexOf('.');
    if (indexDot > 0) {
      String subField = field.substring(indexDot + 1);
      value = extractField(ExpressionParser.toDbObject(object.get(field.substring(0, indexDot))), subField);
    } else {
      value = (T) object.get(field);
    }
    return value;
  }

  /**
   * Can extract field from an object.
   * Handle "field1.field2" in { field1 : {field2 : value2 } }
   *
   * @return null if not found.
   */
  public static  T extractField(DBObject object, List paths) {
    if (object == null) {
      return null; // NPE ?
    }
    DBObject value = object;
    for (String path : paths) {
      value = ExpressionParser.toDbObject(value.get(path));
      if (value == null) {
        break;
      }
    }
    return (T) value;
  }

  /**
   * Say "true" if field is in this object.
   * Handle "field1.field2" in { field1 : {field2 : value2 } }
   *
   * @param object
   * @param field
   * @return true if object contains field.
   */
  public static boolean containsField(DBObject object, String field) {
    if (object == null) {
      return false;
    }
    boolean result;
    int indexDot = field.indexOf('.');
    if (indexDot > 0) {
      String subField = field.substring(indexDot + 1);
      String actualField = field.substring(0, indexDot);
      result = false;
      if (object.containsField(actualField)) {
        Object value = object.get(actualField);
        if (ExpressionParser.isDbObject(value)) {
          result = containsField(ExpressionParser.toDbObject(value), subField);
        }
      }
    } else {
      result = object.containsField(field);
    }
    return result;
  }

  /**
   * Remove field in this object.
   *
   * @param object object to modify
   * @param field  field name, possibly with dot '.' to match hierarchy.
   */
  public static void removeField(DBObject object, String field) {
    if (object == null) {
      return;
    }
    int indexDot = field.indexOf('.');
    if (indexDot > 0) {
      String subField = field.substring(indexDot + 1);
      String actualField = field.substring(0, indexDot);
      if (object.containsField(actualField)) {
        Object value = object.get(actualField);
        if (ExpressionParser.isDbObject(value)) {
          removeField(ExpressionParser.toDbObject(value), subField);
        }
      }
    } else {
      object.removeField(field);
    }
  }

  /**
   * Put a value in a {@link DBObject} with hierarchy.
   *
   * @param dbObject object to modify
   * @param path     field with dot '.' to match hierarchy.
   * @param value    new value to set.
   */
  public static void putValue(DBObject dbObject, String path, Object value) {
    if (dbObject == null) {
      return; // NPE ?
    }
    int indexDot = path.indexOf('.');
    if (indexDot > 0) {
      String field = path.substring(0, indexDot);
      String nextPath = path.substring(indexDot + 1);

      // Create DBObject if necessary
      if (!dbObject.containsField(field)) {
        dbObject.put(field, new BasicDBObject());
      }
      putValue(ExpressionParser.toDbObject(dbObject.get(field)), nextPath, value);
    } else {
      dbObject.put(path, value);
    }
  }

  public static BasicDBList wrap(List otherList) {
    BasicDBList list = new BasicDBList();
    list.addAll(otherList);
    return list;
  }

  public static List split(String key) {
    char dot = '.';
    int index = key.indexOf(dot);
    if (index <= 0) {
      return Collections.singletonList(key);
    } else {
      ArrayList path = new ArrayList(5);
      while (index > 0) {
        path.add(key.substring(0, index));
        key = key.substring(index + 1);
        index = key.indexOf(dot);
      }
      path.add(key);
      return path;
    }
  }

  public static boolean isPositiveInt(String s) {
    for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      if (c < '0' || c > '9') {
        return false;
      }
    }
    return true;
  }

  public static int compareToNullable(String s1, String s2) {
    if (s1 == null) {
      if (s2 == null) {
        return 0;
      } else {
        return -1;
      }
    } else {
      if (s2 == null) {
        return 1;
      } else {
        return s1.compareTo(s2);
      }
    }
  }

  /**
   * @see org.bson.BasicBSONEncoder#_putObjectField(String, Object)
   */
  public static Object clone(Object source) {
    source = BSON.applyEncodingHooks(source);

    if (source instanceof UUID) {
      return source;
    }
    if (ExpressionParser.isDbObject(source)) {
      return clone(ExpressionParser.toDbObject(source));
    }
    if (source instanceof Binary) {
      return ((Binary) source).getData().clone();
    }
    if (source instanceof Date) {
      return new Date(((Date) source).getTime());
    }
    if (source instanceof Character) {
      return source.toString();
    }
    if (source instanceof Number) {
      Number n = (Number) source;
      if (n instanceof Integer ||
          n instanceof Short ||
          n instanceof Byte ||
          n instanceof AtomicInteger) {
        return n.intValue();
      } else if (n instanceof Long || n instanceof AtomicLong) {
        return n.longValue();
      } else if (n instanceof Float || n instanceof Double) {
        return n.doubleValue();
      } else {
        throw new IllegalArgumentException("can't serialize " + n.getClass());
      }
    }
    if (source instanceof byte[]) {
      return makeCopy((byte[]) source);
    }
//    }
//    if(source instanceof Cloneable) {
//      return ((Cloneable) source).clone();
//    }
    return source;
  }

  private static byte[] makeCopy(byte[] source) {
    if (source == null) {
      return null;
    }
    final byte[] copy = new byte[source.length];
    System.arraycopy(source, 0, copy, 0, source.length);
    return copy;
  }

  public static  T clone(T source) {
    if (source == null) {
      return null;
    }

    if (source instanceof BasicDBList) {
      @SuppressWarnings("unchecked")
      T clone = (T) ((BasicDBList) source).copy();
      return clone;
    }

    if (source instanceof org.bson.LazyBSONList) {
      BasicDBList clone = new BasicDBList();
      for (Object o : ((org.bson.LazyBSONList) source)) {
        if (o instanceof DBObject) {
          clone.add(clone(ExpressionParser.toDbObject(o)));
        } else {
          clone.add(o);
        }
      }
      return (T) clone;
    } else if (source instanceof LazyDBList) {
      BasicDBList clone = new BasicDBList();
      for (Object o : ((LazyDBList) source)) {
        if (ExpressionParser.isDbObject(o)) {
          clone.add(clone(ExpressionParser.toDbObject(o)));
        } else {
          clone.add(o);
        }
      }
      return (T) clone;
    }

    if (source instanceof BasicDBObject) {
      @SuppressWarnings("unchecked")
      T clone = (T) ((BasicDBObject) source).copy();
      return clone;
    }

    if (source instanceof LazyBSONObject) {
      @SuppressWarnings("unchecked")
      BasicDBObject clone = new BasicDBObject();
      for (Map.Entry entry : ((LazyBSONObject) source).entrySet()) {
        if (ExpressionParser.isDbObject(entry.getValue())) {
          clone.put(entry.getKey(), clone(ExpressionParser.toDbObject(entry.getValue())));
        } else {
          if (entry.getValue() instanceof Binary) {
            clone.put(entry.getKey(), ((Binary) entry.getValue()).getData().clone());
          } else {
            clone.put(entry.getKey(), entry.getValue());
          }
        }
      }
      return (T) clone;
    }

    @SuppressWarnings("unchecked")
    BasicDBObject clone = new BasicDBObject();
    for (Map.Entry entry : entrySet(source)) {
      if (ExpressionParser.isDbObject(entry.getValue())) {
        clone.put(entry.getKey(), clone(ExpressionParser.toDbObject(entry.getValue())));
      } else {
        if (entry.getValue() instanceof Binary) {
          clone.put(entry.getKey(), ((Binary) entry.getValue()).getData().clone());
        } else {
          clone.put(entry.getKey(), entry.getValue());
        }
      }
    }
    return (T) clone;
  }

  @SuppressWarnings("unchecked")
  public static Set> entrySet(DBObject object) {
    return (Set>) object.toMap().entrySet();
  }

  /**
   * When inserting, MongoDB set _id in first place.
   *
   * @param source source to deep clone, can be null.
   * @return a cloned version of source, with _id field in first.
   */
  public static DBObject cloneIdFirst(DBObject source) {
    if (source == null) {
      return null;
    }

    // copy field values into new object
    DBObject newobj = new BasicDBObject();
    if (source.containsField(FongoDBCollection.ID_FIELD_NAME)) {
      newobj.put(FongoDBCollection.ID_FIELD_NAME, source.get(FongoDBCollection.ID_FIELD_NAME));
    }

    Set> entrySet;
    if (source instanceof LazyBSONObject) {
      entrySet = ((LazyBSONObject) source).entrySet();
    } else if (source instanceof GridFSFile) {
      // GridFSFile.toMap doen't work.
      Map copyMap = new HashMap();
      for (String field : source.keySet()) {
        copyMap.put(field, source.get(field));
      }
      entrySet = copyMap.entrySet();
    } else {
      entrySet = source.toMap().entrySet();
    }
    // need to embedded the sub obj
    for (Map.Entry entry : entrySet) {
      String field = entry.getKey();
      if (!FongoDBCollection.ID_FIELD_NAME.equals(field)) {
        Object val = entry.getValue();
        if (ExpressionParser.isDbObject(val)) {
          newobj.put(field, clone(ExpressionParser.toDbObject(val)));
        } else {
          newobj.put(field, clone(val));
        }
      }
    }
    return newobj;
  }

  /**
   * @return true if the dbObject is empty.
   */
  public static boolean isDBObjectEmpty(DBObject projection) {
    return projection == null || projection.keySet().isEmpty();
  }

  public static Collection toCollection(Object array) {
    int length = Array.getLength(array);
    List list = new ArrayList();
    for (int i = 0; i < length; i++) {
      list.add(Array.get(array, i));
    }
    return list;
  }

  public static List toList(Collection expression) {
    if (expression instanceof List) {
      return (List) expression;
    }
    List list = new ArrayList();
    for (Object object : expression) {
      list.add(object);
    }
    return list;
  }

  public static Number genericAdd(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return left.doubleValue() + right.doubleValue();
    } else if (left instanceof Integer && right instanceof Integer) {
      return left.intValue() + right.intValue();
    } else {
      return left.longValue() + right.longValue();
    }
  }

  public static Number genericSub(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return left.doubleValue() - right.doubleValue();
    } else if (left instanceof Integer && right instanceof Integer) {
      return left.intValue() - right.intValue();
    } else {
      return left.longValue() - right.longValue();
    }
  }

  // http://docs.mongodb.org/manual/faq/developers/#faq-developers-multiplication-type-conversion
  public static Number genericMul(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return left.doubleValue() * (right.doubleValue());
    } else if (left instanceof Integer && right instanceof Integer) {
      return left.intValue() * right.intValue();
    } else {
      return left.longValue() * right.longValue();
    }
  }

  public static Number genericDiv(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return left.doubleValue() / (right.doubleValue());
    } else if (left instanceof Integer && right instanceof Integer) {
      return left.intValue() / right.intValue();
    } else {
      return left.longValue() / right.longValue();
    }
  }

  public static Number genericMod(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return left.doubleValue() % (right.doubleValue());
    } else if (left instanceof Integer && right instanceof Integer) {
      return left.intValue() % right.intValue();
    } else {
      return left.longValue() % right.longValue();
    }
  }

  public static Number genericMax(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return Math.max(left.doubleValue(), right.doubleValue());
    } else if (left instanceof Integer && right instanceof Integer) {
      return Math.max(left.intValue(), right.intValue());
    } else {
      return Math.max(left.longValue(), right.longValue());
    }
  }

  public static Date genericMax(Date left, Date right) {
    if (left == null) {
      return right;
    }
    if (right == null) {
      return left;
    }
    return left.after(right) ? left : right;
  }

  public static Number genericMin(Number left, Number right) {
    if (left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double) {
      return Math.min(left.doubleValue(), right.doubleValue());
    } else if (left instanceof Integer && right instanceof Integer) {
      return Math.min(left.intValue(), right.intValue());
    } else {
      return Math.min(left.longValue(), right.longValue());
    }
  }

  public static Date genericMin(Date left, Date right) {
    if (left == null) {
      return right;
    }
    if (right == null) {
      return left;
    }
    return left.before(right) ? left : right;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy