intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson(
    BSONElement elem, const intrusive_ptr<ExpressionContext>& pExpCtx) {
    uassert(15947, "a group's fields must be specified in an object", elem.type() == Object);

    intrusive_ptr<DocumentSourceGroup> pGroup(DocumentSourceGroup::create(pExpCtx));

    BSONObj groupObj(elem.Obj());
    BSONObjIterator groupIterator(groupObj);
    VariablesIdGenerator idGenerator;
    VariablesParseState vps(&idGenerator);
    while (groupIterator.more()) {
        BSONElement groupField(groupIterator.next());
        const char* pFieldName = groupField.fieldName();

        if (str::equals(pFieldName, "_id")) {
            uassert(
                15948, "a group's _id may only be specified once", pGroup->_idExpressions.empty());
            pGroup->parseIdExpression(groupField, vps);
            invariant(!pGroup->_idExpressions.empty());
        } else if (str::equals(pFieldName, "$doingMerge")) {
            massert(17030, "$doingMerge should be true if present", groupField.Bool());

            pGroup->setDoingMerge(true);
        } else {
            /*
              Treat as a projection field with the additional ability to
              add aggregation operators.
            */
            auto parsedAccumulator = Accumulator::parseAccumulator(groupField, vps);
            auto fieldName = parsedAccumulator.first.toString();
            auto accExpression = parsedAccumulator.second;
            auto factory =
                Accumulator::getFactory(groupField.embeddedObject().firstElementFieldName());

            pGroup->addAccumulator(fieldName, factory, accExpression);
        }
    }

    uassert(15955, "a group specification must include an _id", !pGroup->_idExpressions.empty());

    pGroup->_variables.reset(new Variables(idGenerator.getIdCount()));

    return pGroup;
}
    intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson(
	BSONElement *pBsonElement,
	const intrusive_ptr<ExpressionContext> &pCtx) {
	uassert(15947, "a group's fields must be specified in an object",
		pBsonElement->type() == Object);

        intrusive_ptr<DocumentSourceGroup> pGroup(
	    DocumentSourceGroup::create(pCtx));
        bool idSet = false;

        BSONObj groupObj(pBsonElement->Obj());
        BSONObjIterator groupIterator(groupObj);
        while(groupIterator.more()) {
            BSONElement groupField(groupIterator.next());
            const char *pFieldName = groupField.fieldName();

            if (strcmp(pFieldName, Document::idName.c_str()) == 0) {
		uassert(15948, "a group's _id may only be specified once",
			!idSet);

		BSONType groupType = groupField.type();

		if (groupType == Object) {
		    /*
		      Use the projection-like set of field paths to create the
		      group-by key.
		    */
		    Expression::ObjectCtx oCtx(
			Expression::ObjectCtx::DOCUMENT_OK);
		    intrusive_ptr<Expression> pId(
			Expression::parseObject(&groupField, &oCtx));

		    pGroup->setIdExpression(pId);
		    idSet = true;
		}
		else if (groupType == String) {
		    string groupString(groupField.String());
		    const char *pGroupString = groupString.c_str();
		    if ((groupString.length() == 0) ||
			(pGroupString[0] != '$'))
			goto StringConstantId;

		    string pathString(
			Expression::removeFieldPrefix(groupString));
		    intrusive_ptr<ExpressionFieldPath> pFieldPath(
			ExpressionFieldPath::create(pathString));
		    pGroup->setIdExpression(pFieldPath);
		    idSet = true;
		}
		else {
		    /* pick out the constant types that are allowed */
		    switch(groupType) {
		    case NumberDouble:
		    case String:
		    case Object:
		    case Array:
		    case jstOID:
		    case Bool:
		    case Date:
		    case NumberInt:
		    case Timestamp:
		    case NumberLong:
		    case jstNULL:
		    StringConstantId: // from string case above
		    {
			intrusive_ptr<const Value> pValue(
			    Value::createFromBsonElement(&groupField));
			intrusive_ptr<ExpressionConstant> pConstant(
			    ExpressionConstant::create(pValue));
			pGroup->setIdExpression(pConstant);
			idSet = true;
			break;
		    }

		    default:
			uassert(15949, str::stream() <<
				"a group's _id may not include fields of BSON type " << groupType,
				false);
		    }
		}
            }
            else {
                /*
                  Treat as a projection field with the additional ability to
                  add aggregation operators.
                */
		uassert(15950, str::stream() <<
			"the group aggregate field name " <<
			*pFieldName << " cannot be an operator name",
			*pFieldName != '$');

		uassert(15951, str::stream() << 
			"the group aggregate field " << *pFieldName <<
			"must be defined as an expression inside an object",
			groupField.type() == Object);

                BSONObj subField(groupField.Obj());
                BSONObjIterator subIterator(subField);
                size_t subCount = 0;
                for(; subIterator.more(); ++subCount) {
                    BSONElement subElement(subIterator.next());

                    /* look for the specified operator */
                    GroupOpDesc key;
                    key.pName = subElement.fieldName();
                    const GroupOpDesc *pOp =
			(const GroupOpDesc *)bsearch(
                              &key, GroupOpTable, NGroupOp, sizeof(GroupOpDesc),
                                      GroupOpDescCmp);

		    uassert(15952, str::stream() <<
			    "unknown group operator \"" <<
			    key.pName << "\"",
			    pOp);

                    intrusive_ptr<Expression> pGroupExpr;

                    BSONType elementType = subElement.type();
                    if (elementType == Object) {
			Expression::ObjectCtx oCtx(
			    Expression::ObjectCtx::DOCUMENT_OK);
                        pGroupExpr = Expression::parseObject(
			    &subElement, &oCtx);
		    }
                    else if (elementType == Array) {
			uassert(15953, str::stream() <<
				"aggregating group operators are unary (" <<
				key.pName << ")", false);
                    }
                    else { /* assume its an atomic single operand */
                        pGroupExpr = Expression::parseOperand(&subElement);
                    }

                    pGroup->addAccumulator(
                        pFieldName, pOp->pFactory, pGroupExpr);
                }

		uassert(15954, str::stream() <<
			"the computed aggregate \"" <<
			pFieldName << "\" must specify exactly one operator",
			subCount == 1);
            }
        }

	uassert(15955, "a group specification must include an _id", idSet);

        return pGroup;
    }
    intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson(
            BSONElement elem,
            const intrusive_ptr<ExpressionContext> &pExpCtx) {
        uassert(15947, "a group's fields must be specified in an object",
                elem.type() == Object);

        intrusive_ptr<DocumentSourceGroup> pGroup(
            DocumentSourceGroup::create(pExpCtx));

        BSONObj groupObj(elem.Obj());
        BSONObjIterator groupIterator(groupObj);
        VariablesIdGenerator idGenerator;
        VariablesParseState vps(&idGenerator);
        while(groupIterator.more()) {
            BSONElement groupField(groupIterator.next());
            const char *pFieldName = groupField.fieldName();

            if (str::equals(pFieldName, "_id")) {
                uassert(15948, "a group's _id may only be specified once",
                        pGroup->_idExpressions.empty());
                pGroup->parseIdExpression(groupField, vps);
                invariant(!pGroup->_idExpressions.empty());
            }
            else if (str::equals(pFieldName, "$doingMerge")) {
                massert(17030, "$doingMerge should be true if present",
                        groupField.Bool());

                pGroup->setDoingMerge(true);
            }
            else {
                /*
                  Treat as a projection field with the additional ability to
                  add aggregation operators.
                */
                uassert(16414, str::stream() <<
                        "the group aggregate field name '" << pFieldName <<
                        "' cannot be used because $group's field names cannot contain '.'",
                        !str::contains(pFieldName, '.') );

                uassert(15950, str::stream() <<
                        "the group aggregate field name '" <<
                        pFieldName << "' cannot be an operator name",
                        pFieldName[0] != '$');

                uassert(15951, str::stream() <<
                        "the group aggregate field '" << pFieldName <<
                        "' must be defined as an expression inside an object",
                        groupField.type() == Object);

                BSONObj subField(groupField.Obj());
                BSONObjIterator subIterator(subField);
                size_t subCount = 0;
                for(; subIterator.more(); ++subCount) {
                    BSONElement subElement(subIterator.next());

                    /* look for the specified operator */
                    GroupOpDesc key;
                    key.name = subElement.fieldName();
                    const GroupOpDesc *pOp =
                        (const GroupOpDesc *)bsearch(
                              &key, GroupOpTable, NGroupOp, sizeof(GroupOpDesc),
                                      GroupOpDescCmp);

                    uassert(15952, str::stream() << "unknown group operator '" << key.name << "'",
                            pOp);

                    intrusive_ptr<Expression> pGroupExpr;

                    BSONType elementType = subElement.type();
                    if (elementType == Object) {
                        Expression::ObjectCtx oCtx(Expression::ObjectCtx::DOCUMENT_OK);
                        pGroupExpr = Expression::parseObject(subElement.Obj(), &oCtx, vps);
                    }
                    else if (elementType == Array) {
                        uasserted(15953, str::stream()
                                << "aggregating group operators are unary (" << key.name << ")");
                    }
                    else { /* assume its an atomic single operand */
                        pGroupExpr = Expression::parseOperand(subElement, vps);
                    }

                    pGroup->addAccumulator(pFieldName, pOp->factory, pGroupExpr);
                }

                uassert(15954, str::stream() <<
                        "the computed aggregate '" <<
                        pFieldName << "' must specify exactly one operator",
                        subCount == 1);
            }
        }

        uassert(15955, "a group specification must include an _id",
                !pGroup->_idExpressions.empty());

        pGroup->_variables.reset(new Variables(idGenerator.getIdCount()));

        return pGroup;
    }
intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson(
    BSONElement *pBsonElement,
    const intrusive_ptr<ExpressionContext> &pCtx) {
    assert(pBsonElement->type() == Object); // CW TODO must be an object

    intrusive_ptr<DocumentSourceGroup> pGroup(
        DocumentSourceGroup::create(pCtx));
    bool idSet = false;

    BSONObj groupObj(pBsonElement->Obj());
    BSONObjIterator groupIterator(groupObj);
    while(groupIterator.more()) {
        BSONElement groupField(groupIterator.next());
        const char *pFieldName = groupField.fieldName();

        if (strcmp(pFieldName, Document::idName.c_str()) == 0) {
            assert(!idSet); // CW TODO _id specified multiple times

            BSONType groupType = groupField.type();

            if (groupType == Object) {
                /*
                  Use the projection-like set of field paths to create the
                  group-by key.
                */
                Expression::ObjectCtx oCtx(
                    Expression::ObjectCtx::DOCUMENT_OK);
                intrusive_ptr<Expression> pId(
                    Expression::parseObject(&groupField, &oCtx));

                pGroup->setIdExpression(pId);
                idSet = true;
            }
            else if (groupType == String) {
                string groupString(groupField.String());
                const char *pGroupString = groupString.c_str();
                if ((groupString.length() == 0) ||
                        (pGroupString[0] != '$'))
                    goto StringConstantId;

                string pathString(
                    Expression::removeFieldPrefix(groupString));
                intrusive_ptr<ExpressionFieldPath> pFieldPath(
                    ExpressionFieldPath::create(pathString));
                pGroup->setIdExpression(pFieldPath);
                idSet = true;
            }
            else {
                /* pick out the constant types that are allowed */
                switch(groupType) {
                case NumberDouble:
                case String:
                case Object:
                case Array:
                case jstOID:
                case Bool:
                case Date:
                case NumberInt:
                case Timestamp:
                case NumberLong:
                case jstNULL:
StringConstantId: // from string case above
                    {
                        intrusive_ptr<const Value> pValue(
                            Value::createFromBsonElement(&groupField));
                        intrusive_ptr<ExpressionConstant> pConstant(
                            ExpressionConstant::create(pValue));
                        pGroup->setIdExpression(pConstant);
                        idSet = true;
                        break;
                    }

                default:
                    assert(false);
                    // CW TODO disallowed constant group key
                }
            }
        }
        else {
            /*
              Treat as a projection field with the additional ability to
              add aggregation operators.
            */
            assert(*pFieldName != '$');
            // CW TODO error: field name can't be an operator
            assert(groupField.type() == Object);
            // CW TODO error: must be an operator expression

            BSONObj subField(groupField.Obj());
            BSONObjIterator subIterator(subField);
            size_t subCount = 0;
            for(; subIterator.more(); ++subCount) {
                BSONElement subElement(subIterator.next());

                /* look for the specified operator */
                GroupOpDesc key;
                key.pName = subElement.fieldName();
                const GroupOpDesc *pOp =
                    (const GroupOpDesc *)bsearch(
                        &key, GroupOpTable, NGroupOp, sizeof(GroupOpDesc),
                        GroupOpDescCmp);

                assert(pOp); // CW TODO error: operator not found

                intrusive_ptr<Expression> pGroupExpr;

                BSONType elementType = subElement.type();
                if (elementType == Object) {
                    Expression::ObjectCtx oCtx(
                        Expression::ObjectCtx::DOCUMENT_OK);
                    pGroupExpr = Expression::parseObject(
                                     &subElement, &oCtx);
                }
                else if (elementType == Array) {
                    assert(false); // CW TODO group operators are unary
                }
                else { /* assume its an atomic single operand */
                    pGroupExpr = Expression::parseOperand(&subElement);
                }

                pGroup->addAccumulator(
                    pFieldName, pOp->pFactory, pGroupExpr);
            }

            assert(subCount == 1);
            // CW TODO error: only one operator allowed
        }
    }

    assert(idSet); // CW TODO error: missing _id specification

    return pGroup;
}
    intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson(
        BSONElement *pBsonElement,
        const intrusive_ptr<ExpressionContext> &pExpCtx) {
        uassert(15947, "a group's fields must be specified in an object",
                pBsonElement->type() == Object);

        intrusive_ptr<DocumentSourceGroup> pGroup(
            DocumentSourceGroup::create(pExpCtx));
        bool idSet = false;

        BSONObj groupObj(pBsonElement->Obj());
        BSONObjIterator groupIterator(groupObj);
        while(groupIterator.more()) {
            BSONElement groupField(groupIterator.next());
            const char *pFieldName = groupField.fieldName();

            if (str::equals(pFieldName, "_id")) {
                uassert(15948, "a group's _id may only be specified once",
                        !idSet);

                BSONType groupType = groupField.type();

                if (groupType == Object) {
                    /*
                      Use the projection-like set of field paths to create the
                      group-by key.
                    */
                    Expression::ObjectCtx oCtx(Expression::ObjectCtx::DOCUMENT_OK);
                    intrusive_ptr<Expression> pId(
                        Expression::parseObject(&groupField, &oCtx));

                    pGroup->setIdExpression(pId);
                    idSet = true;
                }
                else if (groupType == String) {
                    const string groupString = groupField.str();
                    if (!groupString.empty() && groupString[0] == '$') {
                        pGroup->setIdExpression(ExpressionFieldPath::parse(groupString));
                        idSet = true;
                    }
                }

                if (!idSet) {
                    // constant id - single group
                    pGroup->setIdExpression(ExpressionConstant::create(Value(groupField)));
                    idSet = true;
                }
            }
            else {
                /*
                  Treat as a projection field with the additional ability to
                  add aggregation operators.
                */
                uassert(16414, str::stream() <<
                        "the group aggregate field name '" << pFieldName <<
                        "' cannot be used because $group's field names cannot contain '.'",
                        !str::contains(pFieldName, '.') );

                uassert(15950, str::stream() <<
                        "the group aggregate field name '" <<
                        pFieldName << "' cannot be an operator name",
                        pFieldName[0] != '$');

                uassert(15951, str::stream() <<
                        "the group aggregate field '" << pFieldName <<
                        "' must be defined as an expression inside an object",
                        groupField.type() == Object);

                BSONObj subField(groupField.Obj());
                BSONObjIterator subIterator(subField);
                size_t subCount = 0;
                for(; subIterator.more(); ++subCount) {
                    BSONElement subElement(subIterator.next());

                    /* look for the specified operator */
                    GroupOpDesc key;
                    key.name = subElement.fieldName();
                    const GroupOpDesc *pOp =
                        (const GroupOpDesc *)bsearch(
                              &key, GroupOpTable, NGroupOp, sizeof(GroupOpDesc),
                                      GroupOpDescCmp);

                    uassert(15952, str::stream() << "unknown group operator '" << key.name << "'",
                            pOp);

                    intrusive_ptr<Expression> pGroupExpr;

                    BSONType elementType = subElement.type();
                    if (elementType == Object) {
                        Expression::ObjectCtx oCtx(
                            Expression::ObjectCtx::DOCUMENT_OK);
                        pGroupExpr = Expression::parseObject(
                            &subElement, &oCtx);
                    }
                    else if (elementType == Array) {
                        uasserted(15953, str::stream()
                                << "aggregating group operators are unary (" << key.name << ")");
                    }
                    else { /* assume its an atomic single operand */
                        pGroupExpr = Expression::parseOperand(&subElement);
                    }

                    pGroup->addAccumulator(pFieldName, pOp->factory, pGroupExpr);
                }

                uassert(15954, str::stream() <<
                        "the computed aggregate '" <<
                        pFieldName << "' must specify exactly one operator",
                        subCount == 1);
            }
        }

        uassert(15955, "a group specification must include an _id", idSet);

        return pGroup;
    }