<commit_before>part of datastore.common;

class Query {
  /**
   * A kind or list of kinds to query
   */
  final Kind kind;
  final Filter filter;
  final List<Property> _groupBy;
  final List<_Ordering> _sortBy;
  
  /**
   * Create a new [Query] which matches against subkinds of the given [Kind]
   */
  Query(Kind kind, Filter filter) :
    this.kind = kind,
    this.filter = filter._checkValidFilterForKind(kind),
    this._groupBy = new List<Property>(),
    this._sortBy = new List<_Ordering>();
  
  /**
   * Group the results of a query by the value of the specified property.
   */
  void groupBy(Property property) {
    if (!kind.properties.keys.contains(property.name)) {
      throw new NoSuchPropertyError(kind, property.name);
    }
    _groupBy.add(property);
  }
  
  /**
   * Sort the results of a query by the value of a specified property.
   * 
   * If [:ascending:] is `true`, the results will be ordered in the direction of increasing value of the property.
   * Otherwise, the results will be ordered in the direction of decreasing value.
   * 
   * If `sortBy` has already been called with a value of another proeprty, the results will be sorted with respect
   * to that proeprty first, and subsequently by the value of the current property.
   */
  void sortBy(Property property, {bool ascending: true}) {
    if (!kind.properties.keys.contains(property.name)) {
      throw new NoSuchPropertyError(kind, property.name);
    }
    this._sortBy.add(new _Ordering(property, ascending));
  }
  
  schema.KindExpression get _kindExpr => kind._toSchemaKindExpression();
  
  Iterable<schema.PropertyReference> get _groupByExpr =>
      _groupBy.map((prop) => prop._toSchemaPropertyReference());
  
  Iterable<schema.PropertyOrder> get _orderExpr =>
      _sortBy.map((ordering) => ordering._toSchemaPropertyOrder());
  
  schema.Query _toSchemaQuery() {
    schema.Query schemaQuery = new schema.Query()
        ..kind.add(_kindExpr)
        ..filter = filter._toSchemaFilter()
        ..groupBy.addAll(_groupByExpr)
        ..order.addAll(_orderExpr);
    return schemaQuery;
  }
}

class _Ordering {
  final Property property;
  final bool isAscending;
  
  _Ordering(Property this.property, bool this.isAscending);
  
  schema.PropertyOrder _toSchemaPropertyOrder() =>
      new schema.PropertyOrder()
          ..property = property._toSchemaPropertyReference()
          ..direction = (
              isAscending 
                  ? schema.PropertyOrder_Direction.ASCENDING 
                  : schema.PropertyOrder_Direction.DESCENDING
          );
  
  bool operator ==(Object other) => 
      other is _Ordering && other.property == property;
  
  int get hashCode => property.hashCode;
}<commit_msg>Added `sortByKey` and subkinds to query<commit_after>part of datastore.common;

class Query {
  /**
   * A kind or list of kinds to query
   */
  final Kind kind;
  final Filter filter;
  final List<Property> _groupBy;
  final List<_Ordering> _sortBy;
  
  /**
   * Create a new [Query] which matches against subkinds of the given [Kind]
   */
  Query(Kind kind, Filter filter) :
    this.kind = kind,
    this.filter = filter._checkValidFilterForKind(kind),
    this._groupBy = new List<Property>(),
    this._sortBy = new List<_Ordering>();
  
  /**
   * Group the results of a query by the value of the specified property.
   */
  void groupBy(Property property) {
    if (!kind.properties.keys.contains(property.name)) {
      throw new NoSuchPropertyError(kind, property.name);
    }
    _groupBy.add(property);
  }
  
  /**
   * Sort the results of a query by the value of a specified property.
   * 
   * If [:ascending:] is `true`, the results will be ordered in the direction of increasing value of the property.
   * Otherwise, the results will be ordered in the direction of decreasing value.
   * 
   * If `sortBy` has already been called with a value of another proeprty, the results will be sorted with respect
   * to that proeprty first, and subsequently by the value of the current property.
   */
  void sortBy(Property property, {bool ascending: true}) {
    if (!kind.properties.keys.contains(property.name)) {
      throw new NoSuchPropertyError(kind, property.name);
    }
    this._sortBy.add(new _Ordering(property, ascending));
  }
  
  /**
   * Sort the results of a query by the value of the key. 
   */
  void sortByKey({bool ascending: true}) {
    this._sortBy.add(new _Ordering(kind._keyProperty, ascending));
  }
  
  Iterable<schema.KindExpression> _kindExpr(Datastore datastore) {
    List<Kind> subKinds = [kind];
    subKinds.addAll(kind._subKinds(datastore));
    return subKinds.map((kind) => kind._toSchemaKindExpression());
  }
  
  Iterable<schema.PropertyReference> get _groupByExpr =>
      _groupBy.map((prop) => prop._toSchemaPropertyReference());
  
  Iterable<schema.PropertyOrder> get _orderExpr =>
      _sortBy.map((ordering) => ordering._toSchemaPropertyOrder());
  
  schema.Query _toSchemaQuery(Datastore datastore) {
    schema.Query schemaQuery = new schema.Query()
        ..kind.addAll(_kindExpr(datastore))
        ..filter = filter._toSchemaFilter()
        ..groupBy.addAll(_groupByExpr)
        ..order.addAll(_orderExpr);
    return schemaQuery;
  }
}

class _Ordering {
  final Property property;
  final bool isAscending;
  
  _Ordering(Property this.property, bool this.isAscending);
  
  schema.PropertyOrder _toSchemaPropertyOrder() =>
      new schema.PropertyOrder()
          ..property = property._toSchemaPropertyReference()
          ..direction = (
              isAscending 
                  ? schema.PropertyOrder_Direction.ASCENDING 
                  : schema.PropertyOrder_Direction.DESCENDING
          );
  
  bool operator ==(Object other) => 
      other is _Ordering && other.property == property;
  
  int get hashCode => property.hashCode;
}
{'fraction_non_alphanumeric': 0.10184237461617196, 'fraction_numerical': 0.0, 'mean_word_length': 3.085714285714286, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6580414', 'n_tokens_mistral': 1730, 'n_tokens_neox': 1691, 'n_words': 483}