text:
package mongo

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/bsoncodec"
	"go.mongodb.org/mongo-driver/bson/bsontype"
	"go.mongodb.org/mongo-driver/mongo/description"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/readpref"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
	"go.mongodb.org/mongo-driver/x/mongo/driver"
	"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
	"go.mongodb.org/mongo-driver/x/mongo/driver/session"
)

// Collection is a handle to a MongoDB collection. It is safe for concurrent use by multiple goroutines.
type Collection struct {
	client         *Client
	db             *Database
	name           string
	readConcern    *readconcern.ReadConcern
	writeConcern   *writeconcern.WriteConcern
	readPreference *readpref.ReadPref
	readSelector   description.ServerSelector
	writeSelector  description.ServerSelector
	registry       *bsoncodec.Registry
}

// aggregateParams is used to store information to configure an Aggregate operation.
type aggregateParams struct {
	ctx            context.Context
	pipeline       interface{}
	client         *Client
	registry       *bsoncodec.Registry
	readConcern    *readconcern.ReadConcern
	writeConcern   *writeconcern.WriteConcern
	retryRead      bool
	db             string
	col            string
	readSelector   description.ServerSelector
	writeSelector  description.ServerSelector
	readPreference *readpref.ReadPref
	opts           []*options.AggregateOptions
}

func closeImplicitSession(sess *session.Client) {
	if sess != nil && sess.SessionType == session.Implicit {
		sess.EndSession()
	}
}

func newCollection(db *Database, name string, opts ...*options.CollectionOptions) *Collection {
	collOpt := options.MergeCollectionOptions(opts...)

	rc := db.readConcern
	if collOpt.ReadConcern != nil {
		rc = collOpt.ReadConcern
	}

	wc := db.writeConcern
	if collOpt.WriteConcern != nil {
		wc = collOpt.WriteConcern
	}

	rp := db.readPreference
	if collOpt.ReadPreference != nil {
		rp = collOpt.ReadPreference
	}

	reg := db.registry
	if collOpt.Registry != nil {
		reg = collOpt.Registry
	}

	readSelector := description.CompositeSelector([]description.ServerSelector{
		description.ReadPrefSelector(rp),
		description.LatencySelector(db.client.localThreshold),
	})

	writeSelector := description.CompositeSelector([]description.ServerSelector{
		description.WriteSelector(),
		description.LatencySelector(db.client.localThreshold),
	})

	coll := &Collection{
		client:         db.client,
		db:             db,
		name:           name,
		readPreference: rp,
		readConcern:    rc,
		writeConcern:   wc,
		readSelector:   readSelector,
		writeSelector:  writeSelector,
		registry:       reg,
	}

	return coll
}

func (coll *Collection) copy() *Collection {
	return &Collection{
		client:         coll.client,
		db:             coll.db,
		name:           coll.name,
		readConcern:    coll.readConcern,
		writeConcern:   coll.writeConcern,
		readPreference: coll.readPreference,
		readSelector:   coll.readSelector,
		writeSelector:  coll.writeSelector,
		registry:       coll.registry,
	}
}

// Clone creates a copy of the Collection configured with the given CollectionOptions.
// The specified options are merged with the existing options on the collection, with the specified options taking
// precedence.
func (coll *Collection) Clone(opts ...*options.CollectionOptions) (*Collection, error) {
	copyColl := coll.copy()
	optsColl := options.MergeCollectionOptions(opts...)

	if optsColl.ReadConcern != nil {
		copyColl.readConcern = optsColl.ReadConcern
	}

	if optsColl.WriteConcern != nil {
		copyColl.writeConcern = optsColl.WriteConcern
	}

	if optsColl.ReadPreference != nil {
		copyColl.readPreference = optsColl.ReadPreference
	}

	if optsColl.Registry != nil {
		copyColl.registry = optsColl.Registry
	}

	copyColl.readSelector = description.CompositeSelector([]description.ServerSelector{
		description.ReadPrefSelector(copyColl.readPreference),
		description.LatencySelector(copyColl.client.localThreshold),
	})

	return copyColl, nil
}

// Name returns the name of the collection.
func (coll *Collection) Name() string {
	return coll.name
}

// Database returns the Database that was used to create the Collection.
func (coll *Collection) Database() *Database {
	return coll.db
}

// BulkWrite performs a bulk write operation (https://docs.mongodb.com/manual/core/bulk-write-operations/).
//
// The models parameter must be a slice of operations to be executed in this bulk write. It cannot be nil or empty.
// All of the models must be non-nil. See the mongo.WriteModel documentation for a list of valid model types and
// examples of how they should be used.
//
// The opts parameter can be used to specify options for the operation (see the options.BulkWriteOptions documentation.)
func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel,
	opts ...*options.BulkWriteOptions) (*BulkWriteResult, error) {

	if len(models) == 0 {
		return nil, ErrEmptySlice
	}

	if ctx == nil {
		ctx = context.Background()
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		var err error
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
		defer sess.EndSession()
	}

	err := coll.client.validSession(sess)
	if err != nil {
		return nil, err
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	for _, model := range models {
		if model == nil {
			return nil, ErrNilDocument
		}
	}

	bwo := options.MergeBulkWriteOptions(opts...)

	op := bulkWrite{
		ordered:                  bwo.Ordered,
		bypassDocumentValidation: bwo.BypassDocumentValidation,
		models:                   models,
		session:                  sess,
		collection:               coll,
		selector:                 selector,
		writeConcern:             wc,
	}

	err = op.execute(ctx)

	return &op.result, replaceErrors(err)
}

func (coll *Collection) insert(ctx context.Context, documents []interface{},
	opts ...*options.InsertManyOptions) ([]interface{}, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	result := make([]interface{}, len(documents))
	docs := make([]bsoncore.Document, len(documents))

	for i, doc := range documents {
		var err error
		docs[i], result[i], err = transformAndEnsureID(coll.registry, doc)
		if err != nil {
			return nil, err
		}
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		var err error
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
		defer sess.EndSession()
	}

	err := coll.client.validSession(sess)
	if err != nil {
		return nil, err
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	op := operation.NewInsert(docs...).
		Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
		ServerSelector(selector).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).
		Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true).
		ServerAPI(coll.client.serverAPI)
	imo := options.MergeInsertManyOptions(opts...)
	if imo.BypassDocumentValidation != nil && *imo.BypassDocumentValidation {
		op = op.BypassDocumentValidation(*imo.BypassDocumentValidation)
	}
	if imo.Ordered != nil {
		op = op.Ordered(*imo.Ordered)
	}
	retry := driver.RetryNone
	if coll.client.retryWrites {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)

	err = op.Execute(ctx)
	wce, ok := err.(driver.WriteCommandError)
	if !ok {
		return result, err
	}

	// remove the ids that had writeErrors from result
	for i, we := range wce.WriteErrors {
		// i indexes have been removed before the current error, so the index is we.Index-i
		idIndex := int(we.Index) - i
		// if the insert is ordered, nothing after the error was inserted
		if imo.Ordered == nil || *imo.Ordered {
			result = result[:idIndex]
			break
		}
		result = append(result[:idIndex], result[idIndex+1:]...)
	}

	return result, err
}

// InsertOne executes an insert command to insert a single document into the collection.
//
// The document parameter must be the document to be inserted. It cannot be nil. If the document does not have an _id
// field when transformed into BSON, one will be added automatically to the marshalled document. The original document
// will not be modified. The _id can be retrieved from the InsertedID field of the returned InsertOneResult.
//
// The opts parameter can be used to specify options for the operation (see the options.InsertOneOptions documentation.)
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/insert/.
func (coll *Collection) InsertOne(ctx context.Context, document interface{},
	opts ...*options.InsertOneOptions) (*InsertOneResult, error) {

	ioOpts := options.MergeInsertOneOptions(opts...)
	imOpts := options.InsertMany()

	if ioOpts.BypassDocumentValidation != nil && *ioOpts.BypassDocumentValidation {
		imOpts.SetBypassDocumentValidation(*ioOpts.BypassDocumentValidation)
	}
	res, err := coll.insert(ctx, []interface{}{document}, imOpts)

	rr, err := processWriteError(err)
	if rr&rrOne == 0 {
		return nil, err
	}
	return &InsertOneResult{InsertedID: res[0]}, err
}

// InsertMany executes an insert command to insert multiple documents into the collection. If write errors occur
// during the operation (e.g. duplicate key error), this method returns a BulkWriteException error.
//
// The documents parameter must be a slice of documents to insert. The slice cannot be nil or empty. The elements must
// all be non-nil. For any document that does not have an _id field when transformed into BSON, one will be added
// automatically to the marshalled document. The original document will not be modified. The _id values for the inserted
// documents can be retrieved from the InsertedIDs field of the returned InsertManyResult.
//
// The opts parameter can be used to specify options for the operation (see the options.InsertManyOptions documentation.)
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/insert/.
func (coll *Collection) InsertMany(ctx context.Context, documents []interface{},
	opts ...*options.InsertManyOptions) (*InsertManyResult, error) {

	if len(documents) == 0 {
		return nil, ErrEmptySlice
	}

	result, err := coll.insert(ctx, documents, opts...)
	rr, err := processWriteError(err)
	if rr&rrMany == 0 {
		return nil, err
	}

	imResult := &InsertManyResult{InsertedIDs: result}
	writeException, ok := err.(WriteException)
	if !ok {
		return imResult, err
	}

	// create and return a BulkWriteException
	bwErrors := make([]BulkWriteError, 0, len(writeException.WriteErrors))
	for _, we := range writeException.WriteErrors {
		bwErrors = append(bwErrors, BulkWriteError{
			WriteError: we,
			Request:    nil,
		})
	}

	return imResult, BulkWriteException{
		WriteErrors:       bwErrors,
		WriteConcernError: writeException.WriteConcernError,
		Labels:            writeException.Labels,
	}
}

func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOne bool, expectedRr returnResult,
	opts ...*options.DeleteOptions) (*DeleteResult, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
		defer sess.EndSession()
	}

	err = coll.client.validSession(sess)
	if err != nil {
		return nil, err
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	var limit int32
	if deleteOne {
		limit = 1
	}
	do := options.MergeDeleteOptions(opts...)
	didx, doc := bsoncore.AppendDocumentStart(nil)
	doc = bsoncore.AppendDocumentElement(doc, "q", f)
	doc = bsoncore.AppendInt32Element(doc, "limit", limit)
	if do.Collation != nil {
		doc = bsoncore.AppendDocumentElement(doc, "collation", do.Collation.ToDocument())
	}
	if do.Hint != nil {
		hint, err := transformValue(coll.registry, do.Hint, false, "hint")
		if err != nil {
			return nil, err
		}

		doc = bsoncore.AppendValueElement(doc, "hint", hint)
	}
	doc, _ = bsoncore.AppendDocumentEnd(doc, didx)

	op := operation.NewDelete(doc).
		Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
		ServerSelector(selector).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).
		Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true).
		ServerAPI(coll.client.serverAPI)
	if do.Hint != nil {
		op = op.Hint(true)
	}

	// deleteMany cannot be retried
	retryMode := driver.RetryNone
	if deleteOne && coll.client.retryWrites {
		retryMode = driver.RetryOncePerCommand
	}
	op = op.Retry(retryMode)
	rr, err := processWriteError(op.Execute(ctx))
	if rr&expectedRr == 0 {
		return nil, err
	}
	return &DeleteResult{DeletedCount: int64(op.Result().N)}, err
}

// DeleteOne executes a delete command to delete at most one document from the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// deleted. It cannot be nil. If the filter does not match any documents, the operation will succeed and a DeleteResult
// with a DeletedCount of 0 will be returned. If the filter matches multiple documents, one will be selected from the
// matched set.
//
// The opts parameter can be used to specify options for the operation (see the options.DeleteOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/delete/.
func (coll *Collection) DeleteOne(ctx context.Context, filter interface{},
	opts ...*options.DeleteOptions) (*DeleteResult, error) {

	return coll.delete(ctx, filter, true, rrOne, opts...)
}

// DeleteMany executes a delete command to delete documents from the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the documents to
// be deleted. It cannot be nil. An empty document (e.g. bson.D{}) should be used to delete all documents in the
// collection. If the filter does not match any documents, the operation will succeed and a DeleteResult with a
// DeletedCount of 0 will be returned.
//
// The opts parameter can be used to specify options for the operation (see the options.DeleteOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/delete/.
func (coll *Collection) DeleteMany(ctx context.Context, filter interface{},
	opts ...*options.DeleteOptions) (*DeleteResult, error) {

	return coll.delete(ctx, filter, false, rrMany, opts...)
}

func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Document, update interface{}, multi bool,
	expectedRr returnResult, checkDollarKey bool, opts ...*options.UpdateOptions) (*UpdateResult, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	uo := options.MergeUpdateOptions(opts...)

	// collation, arrayFilters, upsert, and hint are included on the individual update documents rather than as part of the
	// command
	updateDoc, err := createUpdateDoc(filter, update, uo.Hint, uo.ArrayFilters, uo.Collation, uo.Upsert, multi,
		checkDollarKey, coll.registry)
	if err != nil {
		return nil, err
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		var err error
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
		defer sess.EndSession()
	}

	err = coll.client.validSession(sess)
	if err != nil {
		return nil, err
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	op := operation.NewUpdate(updateDoc).
		Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
		ServerSelector(selector).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).
		Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Hint(uo.Hint != nil).
		ArrayFilters(uo.ArrayFilters != nil).Ordered(true).ServerAPI(coll.client.serverAPI)

	if uo.BypassDocumentValidation != nil && *uo.BypassDocumentValidation {
		op = op.BypassDocumentValidation(*uo.BypassDocumentValidation)
	}
	retry := driver.RetryNone
	// retryable writes are only enabled updateOne/replaceOne operations
	if !multi && coll.client.retryWrites {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)
	err = op.Execute(ctx)

	rr, err := processWriteError(err)
	if rr&expectedRr == 0 {
		return nil, err
	}

	opRes := op.Result()
	res := &UpdateResult{
		MatchedCount:  int64(opRes.N),
		ModifiedCount: int64(opRes.NModified),
		UpsertedCount: int64(len(opRes.Upserted)),
	}
	if len(opRes.Upserted) > 0 {
		res.UpsertedID = opRes.Upserted[0].ID
		res.MatchedCount--
	}

	return res, err
}

// UpdateByID executes an update command to update the document whose _id value matches the provided ID in the collection.
// This is equivalent to running UpdateOne(ctx, bson.D{{"_id", id}}, update, opts...).
//
// The id parameter is the _id of the document to be updated. It cannot be nil. If the ID does not match any documents,
// the operation will succeed and an UpdateResult with a MatchedCount of 0 will be returned.
//
// The update parameter must be a document containing update operators
// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be
// made to the selected document. It cannot be nil or empty.
//
// The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/.
func (coll *Collection) UpdateByID(ctx context.Context, id interface{}, update interface{},
	opts ...*options.UpdateOptions) (*UpdateResult, error) {
	if id == nil {
		return nil, ErrNilValue
	}
	return coll.UpdateOne(ctx, bson.D{{"_id", id}}, update, opts...)
}

// UpdateOne executes an update command to update at most one document in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// updated. It cannot be nil. If the filter does not match any documents, the operation will succeed and an UpdateResult
// with a MatchedCount of 0 will be returned. If the filter matches multiple documents, one will be selected from the
// matched set and MatchedCount will equal 1.
//
// The update parameter must be a document containing update operators
// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be
// made to the selected document. It cannot be nil or empty.
//
// The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/.
func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, update interface{},
	opts ...*options.UpdateOptions) (*UpdateResult, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	return coll.updateOrReplace(ctx, f, update, false, rrOne, true, opts...)
}

// UpdateMany executes an update command to update documents in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the documents to be
// updated. It cannot be nil. If the filter does not match any documents, the operation will succeed and an UpdateResult
// with a MatchedCount of 0 will be returned.
//
// The update parameter must be a document containing update operators
// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be made
// to the selected documents. It cannot be nil or empty.
//
// The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/.
func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, update interface{},
	opts ...*options.UpdateOptions) (*UpdateResult, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	return coll.updateOrReplace(ctx, f, update, true, rrMany, true, opts...)
}

// ReplaceOne executes an update command to replace at most one document in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// replaced. It cannot be nil. If the filter does not match any documents, the operation will succeed and an
// UpdateResult with a MatchedCount of 0 will be returned. If the filter matches multiple documents, one will be
// selected from the matched set and MatchedCount will equal 1.
//
// The replacement parameter must be a document that will be used to replace the selected document. It cannot be nil
// and cannot contain any update operators (https://docs.mongodb.com/manual/reference/operator/update/).
//
// The opts parameter can be used to specify options for the operation (see the options.ReplaceOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/.
func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{},
	replacement interface{}, opts ...*options.ReplaceOptions) (*UpdateResult, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	r, err := transformBsoncoreDocument(coll.registry, replacement, true, "replacement")
	if err != nil {
		return nil, err
	}

	if err := ensureNoDollarKey(r); err != nil {
		return nil, err
	}

	updateOptions := make([]*options.UpdateOptions, 0, len(opts))
	for _, opt := range opts {
		uOpts := options.Update()
		uOpts.BypassDocumentValidation = opt.BypassDocumentValidation
		uOpts.Collation = opt.Collation
		uOpts.Upsert = opt.Upsert
		uOpts.Hint = opt.Hint
		updateOptions = append(updateOptions, uOpts)
	}

	return coll.updateOrReplace(ctx, f, r, false, rrOne, false, updateOptions...)
}

// Aggregate executes an aggregate command against the collection and returns a cursor over the resulting documents.
//
// The pipeline parameter must be an array of documents, each representing an aggregation stage. The pipeline cannot
// be nil but can be empty. The stage documents must all be non-nil. For a pipeline of bson.D documents, the
// mongo.Pipeline type can be used. See
// https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/#db-collection-aggregate-stages for a list of
// valid stages in aggregations.
//
// The opts parameter can be used to specify options for the operation (see the options.AggregateOptions documentation.)
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/aggregate/.
func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{},
	opts ...*options.AggregateOptions) (*Cursor, error) {
	a := aggregateParams{
		ctx:            ctx,
		pipeline:       pipeline,
		client:         coll.client,
		registry:       coll.registry,
		readConcern:    coll.readConcern,
		writeConcern:   coll.writeConcern,
		retryRead:      coll.client.retryReads,
		db:             coll.db.name,
		col:            coll.name,
		readSelector:   coll.readSelector,
		writeSelector:  coll.writeSelector,
		readPreference: coll.readPreference,
		opts:           opts,
	}
	return aggregate(a)
}

// aggreate is the helper method for Aggregate
func aggregate(a aggregateParams) (*Cursor, error) {

	if a.ctx == nil {
		a.ctx = context.Background()
	}

	pipelineArr, hasOutputStage, err := transformAggregatePipeline(a.registry, a.pipeline)
	if err != nil {
		return nil, err
	}

	sess := sessionFromContext(a.ctx)
	if sess == nil && a.client.sessionPool != nil {
		sess, err = session.NewClientSession(a.client.sessionPool, a.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
	}
	if err = a.client.validSession(sess); err != nil {
		return nil, err
	}

	var wc *writeconcern.WriteConcern
	if hasOutputStage {
		wc = a.writeConcern
	}
	rc := a.readConcern
	if sess.TransactionRunning() {
		wc = nil
		rc = nil
	}
	if !writeconcern.AckWrite(wc) {
		closeImplicitSession(sess)
		sess = nil
	}

	selector := makePinnedSelector(sess, a.writeSelector)
	if !hasOutputStage {
		selector = makeReadPrefSelector(sess, a.readSelector, a.client.localThreshold)
	}

	ao := options.MergeAggregateOptions(a.opts...)
	cursorOpts := a.client.createBaseCursorOptions()

	op := operation.NewAggregate(pipelineArr).
		Session(sess).
		WriteConcern(wc).
		ReadConcern(rc).
		CommandMonitor(a.client.monitor).
		ServerSelector(selector).
		ClusterClock(a.client.clock).
		Database(a.db).
		Collection(a.col).
		Deployment(a.client.deployment).
		Crypt(a.client.cryptFLE).
		ServerAPI(a.client.serverAPI)
	if !hasOutputStage {
		// Only pass the user-specified read preference if the aggregation doesn't have a $out or $merge stage.
		// Otherwise, the read preference could be forwarded to a mongos, which would error if the aggregation were
		// executed against a non-primary node.
		op.ReadPreference(a.readPreference)
	}

	if ao.AllowDiskUse != nil {
		op.AllowDiskUse(*ao.AllowDiskUse)
	}
	// ignore batchSize of 0 with $out
	if ao.BatchSize != nil && !(*ao.BatchSize == 0 && hasOutputStage) {
		op.BatchSize(*ao.BatchSize)
		cursorOpts.BatchSize = *ao.BatchSize
	}
	if ao.BypassDocumentValidation != nil && *ao.BypassDocumentValidation {
		op.BypassDocumentValidation(*ao.BypassDocumentValidation)
	}
	if ao.Collation != nil {
		op.Collation(bsoncore.Document(ao.Collation.ToDocument()))
	}
	if ao.MaxTime != nil {
		op.MaxTimeMS(int64(*ao.MaxTime / time.Millisecond))
	}
	if ao.MaxAwaitTime != nil {
		cursorOpts.MaxTimeMS = int64(*ao.MaxAwaitTime / time.Millisecond)
	}
	if ao.Comment != nil {
		op.Comment(*ao.Comment)
	}
	if ao.Hint != nil {
		hintVal, err := transformValue(a.registry, ao.Hint, false, "hint")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Hint(hintVal)
	}
	if ao.Let != nil {
		let, err := transformBsoncoreDocument(a.registry, ao.Let, true, "let")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Let(let)
	}

	retry := driver.RetryNone
	if a.retryRead && !hasOutputStage {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)

	err = op.Execute(a.ctx)
	if err != nil {
		closeImplicitSession(sess)
		if wce, ok := err.(driver.WriteCommandError); ok && wce.WriteConcernError != nil {
			return nil, *convertDriverWriteConcernError(wce.WriteConcernError)
		}
		return nil, replaceErrors(err)
	}

	bc, err := op.Result(cursorOpts)
	if err != nil {
		closeImplicitSession(sess)
		return nil, replaceErrors(err)
	}
	cursor, err := newCursorWithSession(bc, a.registry, sess)
	return cursor, replaceErrors(err)
}

// CountDocuments returns the number of documents in the collection. For a fast count of the documents in the
// collection, see the EstimatedDocumentCount method.
//
// The filter parameter must be a document and can be used to select which documents contribute to the count. It
// cannot be nil. An empty document (e.g. bson.D{}) should be used to count all documents in the collection. This will
// result in a full collection scan.
//
// The opts parameter can be used to specify options for the operation (see the options.CountOptions documentation).
func (coll *Collection) CountDocuments(ctx context.Context, filter interface{},
	opts ...*options.CountOptions) (int64, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	countOpts := options.MergeCountOptions(opts...)

	pipelineArr, err := countDocumentsAggregatePipeline(coll.registry, filter, countOpts)
	if err != nil {
		return 0, err
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return 0, err
		}
		defer sess.EndSession()
	}
	if err = coll.client.validSession(sess); err != nil {
		return 0, err
	}

	rc := coll.readConcern
	if sess.TransactionRunning() {
		rc = nil
	}

	selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold)
	op := operation.NewAggregate(pipelineArr).Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference).
		CommandMonitor(coll.client.monitor).ServerSelector(selector).ClusterClock(coll.client.clock).Database(coll.db.name).
		Collection(coll.name).Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI)
	if countOpts.Collation != nil {
		op.Collation(bsoncore.Document(countOpts.Collation.ToDocument()))
	}
	if countOpts.MaxTime != nil {
		op.MaxTimeMS(int64(*countOpts.MaxTime / time.Millisecond))
	}
	if countOpts.Hint != nil {
		hintVal, err := transformValue(coll.registry, countOpts.Hint, false, "hint")
		if err != nil {
			return 0, err
		}
		op.Hint(hintVal)
	}
	retry := driver.RetryNone
	if coll.client.retryReads {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)

	err = op.Execute(ctx)
	if err != nil {
		return 0, replaceErrors(err)
	}

	batch := op.ResultCursorResponse().FirstBatch
	if batch == nil {
		return 0, errors.New("invalid response from server, no 'firstBatch' field")
	}

	docs, err := batch.Documents()
	if err != nil || len(docs) == 0 {
		return 0, nil
	}

	val, ok := docs[0].Lookup("n").AsInt64OK()
	if !ok {
		return 0, errors.New("invalid response from server, no 'n' field")
	}

	return val, nil
}

// EstimatedDocumentCount executes a count command and returns an estimate of the number of documents in the collection
// using collection metadata.
//
// The opts parameter can be used to specify options for the operation (see the options.EstimatedDocumentCountOptions
// documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/count/.
func (coll *Collection) EstimatedDocumentCount(ctx context.Context,
	opts ...*options.EstimatedDocumentCountOptions) (int64, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	sess := sessionFromContext(ctx)

	var err error
	if sess == nil && coll.client.sessionPool != nil {
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return 0, err
		}
		defer sess.EndSession()
	}

	err = coll.client.validSession(sess)
	if err != nil {
		return 0, err
	}

	rc := coll.readConcern
	if sess.TransactionRunning() {
		rc = nil
	}

	selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold)
	op := operation.NewCount().Session(sess).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor).
		Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference).
		ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI)

	co := options.MergeEstimatedDocumentCountOptions(opts...)
	if co.MaxTime != nil {
		op = op.MaxTimeMS(int64(*co.MaxTime / time.Millisecond))
	}
	retry := driver.RetryNone
	if coll.client.retryReads {
		retry = driver.RetryOncePerCommand
	}
	op.Retry(retry)

	err = op.Execute(ctx)

	return op.Result().N, replaceErrors(err)
}

// Distinct executes a distinct command to find the unique values for a specified field in the collection.
//
// The fieldName parameter specifies the field name for which distinct values should be returned.
//
// The filter parameter must be a document containing query operators and can be used to select which documents are
// considered. It cannot be nil. An empty document (e.g. bson.D{}) should be used to select all documents.
//
// The opts parameter can be used to specify options for the operation (see the options.DistinctOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/distinct/.
func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter interface{},
	opts ...*options.DistinctOptions) ([]interface{}, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	sess := sessionFromContext(ctx)

	if sess == nil && coll.client.sessionPool != nil {
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
		defer sess.EndSession()
	}

	err = coll.client.validSession(sess)
	if err != nil {
		return nil, err
	}

	rc := coll.readConcern
	if sess.TransactionRunning() {
		rc = nil
	}

	selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold)
	option := options.MergeDistinctOptions(opts...)

	op := operation.NewDistinct(fieldName, bsoncore.Document(f)).
		Session(sess).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor).
		Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference).
		ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI)

	if option.Collation != nil {
		op.Collation(bsoncore.Document(option.Collation.ToDocument()))
	}
	if option.MaxTime != nil {
		op.MaxTimeMS(int64(*option.MaxTime / time.Millisecond))
	}
	retry := driver.RetryNone
	if coll.client.retryReads {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)

	err = op.Execute(ctx)
	if err != nil {
		return nil, replaceErrors(err)
	}

	arr, ok := op.Result().Values.ArrayOK()
	if !ok {
		return nil, fmt.Errorf("response field 'values' is type array, but received BSON type %s", op.Result().Values.Type)
	}

	values, err := arr.Values()
	if err != nil {
		return nil, err
	}

	retArray := make([]interface{}, len(values))

	for i, val := range values {
		raw := bson.RawValue{Type: val.Type, Value: val.Data}
		err = raw.Unmarshal(&retArray[i])
		if err != nil {
			return nil, err
		}
	}

	return retArray, replaceErrors(err)
}

// Find executes a find command and returns a Cursor over the matching documents in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select which documents are
// included in the result. It cannot be nil. An empty document (e.g. bson.D{}) should be used to include all documents.
//
// The opts parameter can be used to specify options for the operation (see the options.FindOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/find/.
func (coll *Collection) Find(ctx context.Context, filter interface{},
	opts ...*options.FindOptions) (*Cursor, error) {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return nil, err
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		var err error
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return nil, err
		}
	}

	err = coll.client.validSession(sess)
	if err != nil {
		closeImplicitSession(sess)
		return nil, err
	}

	rc := coll.readConcern
	if sess.TransactionRunning() {
		rc = nil
	}

	selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold)
	op := operation.NewFind(f).
		Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference).
		CommandMonitor(coll.client.monitor).ServerSelector(selector).
		ClusterClock(coll.client.clock).Database(coll.db.name).Collection(coll.name).
		Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI)

	fo := options.MergeFindOptions(opts...)
	cursorOpts := coll.client.createBaseCursorOptions()

	if fo.AllowDiskUse != nil {
		op.AllowDiskUse(*fo.AllowDiskUse)
	}
	if fo.AllowPartialResults != nil {
		op.AllowPartialResults(*fo.AllowPartialResults)
	}
	if fo.BatchSize != nil {
		cursorOpts.BatchSize = *fo.BatchSize
		op.BatchSize(*fo.BatchSize)
	}
	if fo.Collation != nil {
		op.Collation(bsoncore.Document(fo.Collation.ToDocument()))
	}
	if fo.Comment != nil {
		op.Comment(*fo.Comment)
	}
	if fo.CursorType != nil {
		switch *fo.CursorType {
		case options.Tailable:
			op.Tailable(true)
		case options.TailableAwait:
			op.Tailable(true)
			op.AwaitData(true)
		}
	}
	if fo.Hint != nil {
		hint, err := transformValue(coll.registry, fo.Hint, false, "hint")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Hint(hint)
	}
	if fo.Limit != nil {
		limit := *fo.Limit
		if limit < 0 {
			limit = -1 * limit
			op.SingleBatch(true)
		}
		cursorOpts.Limit = int32(limit)
		op.Limit(limit)
	}
	if fo.Max != nil {
		max, err := transformBsoncoreDocument(coll.registry, fo.Max, true, "max")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Max(max)
	}
	if fo.MaxAwaitTime != nil {
		cursorOpts.MaxTimeMS = int64(*fo.MaxAwaitTime / time.Millisecond)
	}
	if fo.MaxTime != nil {
		op.MaxTimeMS(int64(*fo.MaxTime / time.Millisecond))
	}
	if fo.Min != nil {
		min, err := transformBsoncoreDocument(coll.registry, fo.Min, true, "min")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Min(min)
	}
	if fo.NoCursorTimeout != nil {
		op.NoCursorTimeout(*fo.NoCursorTimeout)
	}
	if fo.OplogReplay != nil {
		op.OplogReplay(*fo.OplogReplay)
	}
	if fo.Projection != nil {
		proj, err := transformBsoncoreDocument(coll.registry, fo.Projection, true, "projection")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Projection(proj)
	}
	if fo.ReturnKey != nil {
		op.ReturnKey(*fo.ReturnKey)
	}
	if fo.ShowRecordID != nil {
		op.ShowRecordID(*fo.ShowRecordID)
	}
	if fo.Skip != nil {
		op.Skip(*fo.Skip)
	}
	if fo.Snapshot != nil {
		op.Snapshot(*fo.Snapshot)
	}
	if fo.Sort != nil {
		sort, err := transformBsoncoreDocument(coll.registry, fo.Sort, false, "sort")
		if err != nil {
			closeImplicitSession(sess)
			return nil, err
		}
		op.Sort(sort)
	}
	retry := driver.RetryNone
	if coll.client.retryReads {
		retry = driver.RetryOncePerCommand
	}
	op = op.Retry(retry)

	if err = op.Execute(ctx); err != nil {
		closeImplicitSession(sess)
		return nil, replaceErrors(err)
	}

	bc, err := op.Result(cursorOpts)
	if err != nil {
		closeImplicitSession(sess)
		return nil, replaceErrors(err)
	}
	return newCursorWithSession(bc, coll.registry, sess)
}

// FindOne executes a find command and returns a SingleResult for one document in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// returned. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments will be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The opts parameter can be used to specify options for this operation (see the options.FindOneOptions documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/find/.
func (coll *Collection) FindOne(ctx context.Context, filter interface{},
	opts ...*options.FindOneOptions) *SingleResult {

	if ctx == nil {
		ctx = context.Background()
	}

	findOpts := make([]*options.FindOptions, len(opts))
	for i, opt := range opts {
		findOpts[i] = &options.FindOptions{
			AllowPartialResults: opt.AllowPartialResults,
			BatchSize:           opt.BatchSize,
			Collation:           opt.Collation,
			Comment:             opt.Comment,
			CursorType:          opt.CursorType,
			Hint:                opt.Hint,
			Max:                 opt.Max,
			MaxAwaitTime:        opt.MaxAwaitTime,
			MaxTime:             opt.MaxTime,
			Min:                 opt.Min,
			NoCursorTimeout:     opt.NoCursorTimeout,
			OplogReplay:         opt.OplogReplay,
			Projection:          opt.Projection,
			ReturnKey:           opt.ReturnKey,
			ShowRecordID:        opt.ShowRecordID,
			Skip:                opt.Skip,
			Snapshot:            opt.Snapshot,
			Sort:                opt.Sort,
		}
	}
	// Unconditionally send a limit to make sure only one document is returned and the cursor is not kept open
	// by the server.
	findOpts = append(findOpts, options.Find().SetLimit(-1))

	cursor, err := coll.Find(ctx, filter, findOpts...)
	return &SingleResult{cur: cursor, reg: coll.registry, err: replaceErrors(err)}
}

func (coll *Collection) findAndModify(ctx context.Context, op *operation.FindAndModify) *SingleResult {
	if ctx == nil {
		ctx = context.Background()
	}

	sess := sessionFromContext(ctx)
	var err error
	if sess == nil && coll.client.sessionPool != nil {
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return &SingleResult{err: err}
		}
		defer sess.EndSession()
	}

	err = coll.client.validSession(sess)
	if err != nil {
		return &SingleResult{err: err}
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	retry := driver.RetryNone
	if coll.client.retryWrites {
		retry = driver.RetryOnce
	}

	op = op.Session(sess).
		WriteConcern(wc).
		CommandMonitor(coll.client.monitor).
		ServerSelector(selector).
		ClusterClock(coll.client.clock).
		Database(coll.db.name).
		Collection(coll.name).
		Deployment(coll.client.deployment).
		Retry(retry).
		Crypt(coll.client.cryptFLE)

	_, err = processWriteError(op.Execute(ctx))
	if err != nil {
		return &SingleResult{err: err}
	}

	return &SingleResult{rdr: bson.Raw(op.Result().Value), reg: coll.registry}
}

// FindOneAndDelete executes a findAndModify command to delete at most one document in the collection. and returns the
// document as it appeared before deletion.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// deleted. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments wil be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The opts parameter can be used to specify options for the operation (see the options.FindOneAndDeleteOptions
// documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/.
func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{},
	opts ...*options.FindOneAndDeleteOptions) *SingleResult {

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return &SingleResult{err: err}
	}
	fod := options.MergeFindOneAndDeleteOptions(opts...)
	op := operation.NewFindAndModify(f).Remove(true).ServerAPI(coll.client.serverAPI)
	if fod.Collation != nil {
		op = op.Collation(bsoncore.Document(fod.Collation.ToDocument()))
	}
	if fod.MaxTime != nil {
		op = op.MaxTimeMS(int64(*fod.MaxTime / time.Millisecond))
	}
	if fod.Projection != nil {
		proj, err := transformBsoncoreDocument(coll.registry, fod.Projection, true, "projection")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Fields(proj)
	}
	if fod.Sort != nil {
		sort, err := transformBsoncoreDocument(coll.registry, fod.Sort, false, "sort")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Sort(sort)
	}
	if fod.Hint != nil {
		hint, err := transformValue(coll.registry, fod.Hint, false, "hint")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Hint(hint)
	}

	return coll.findAndModify(ctx, op)
}

// FindOneAndReplace executes a findAndModify command to replace at most one document in the collection
// and returns the document as it appeared before replacement.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// replaced. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments wil be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The replacement parameter must be a document that will be used to replace the selected document. It cannot be nil
// and cannot contain any update operators (https://docs.mongodb.com/manual/reference/operator/update/).
//
// The opts parameter can be used to specify options for the operation (see the options.FindOneAndReplaceOptions
// documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/.
func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{},
	replacement interface{}, opts ...*options.FindOneAndReplaceOptions) *SingleResult {

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return &SingleResult{err: err}
	}
	r, err := transformBsoncoreDocument(coll.registry, replacement, true, "replacement")
	if err != nil {
		return &SingleResult{err: err}
	}
	if firstElem, err := r.IndexErr(0); err == nil && strings.HasPrefix(firstElem.Key(), "$") {
		return &SingleResult{err: errors.New("replacement document cannot contain keys beginning with '$'")}
	}

	fo := options.MergeFindOneAndReplaceOptions(opts...)
	op := operation.NewFindAndModify(f).Update(bsoncore.Value{Type: bsontype.EmbeddedDocument, Data: r}).
		ServerAPI(coll.client.serverAPI)
	if fo.BypassDocumentValidation != nil && *fo.BypassDocumentValidation {
		op = op.BypassDocumentValidation(*fo.BypassDocumentValidation)
	}
	if fo.Collation != nil {
		op = op.Collation(bsoncore.Document(fo.Collation.ToDocument()))
	}
	if fo.MaxTime != nil {
		op = op.MaxTimeMS(int64(*fo.MaxTime / time.Millisecond))
	}
	if fo.Projection != nil {
		proj, err := transformBsoncoreDocument(coll.registry, fo.Projection, true, "projection")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Fields(proj)
	}
	if fo.ReturnDocument != nil {
		op = op.NewDocument(*fo.ReturnDocument == options.After)
	}
	if fo.Sort != nil {
		sort, err := transformBsoncoreDocument(coll.registry, fo.Sort, false, "sort")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Sort(sort)
	}
	if fo.Upsert != nil {
		op = op.Upsert(*fo.Upsert)
	}
	if fo.Hint != nil {
		hint, err := transformValue(coll.registry, fo.Hint, false, "hint")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Hint(hint)
	}

	return coll.findAndModify(ctx, op)
}

// FindOneAndUpdate executes a findAndModify command to update at most one document in the collection and returns the
// document as it appeared before updating.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// updated. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments wil be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The update parameter must be a document containing update operators
// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be made
// to the selected document. It cannot be nil or empty.
//
// The opts parameter can be used to specify options for the operation (see the options.FindOneAndUpdateOptions
// documentation).
//
// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/.
func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{},
	update interface{}, opts ...*options.FindOneAndUpdateOptions) *SingleResult {

	if ctx == nil {
		ctx = context.Background()
	}

	f, err := transformBsoncoreDocument(coll.registry, filter, true, "filter")
	if err != nil {
		return &SingleResult{err: err}
	}

	fo := options.MergeFindOneAndUpdateOptions(opts...)
	op := operation.NewFindAndModify(f).ServerAPI(coll.client.serverAPI)

	u, err := transformUpdateValue(coll.registry, update, true)
	if err != nil {
		return &SingleResult{err: err}
	}
	op = op.Update(u)

	if fo.ArrayFilters != nil {
		filtersDoc, err := fo.ArrayFilters.ToArrayDocument()
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.ArrayFilters(bsoncore.Document(filtersDoc))
	}
	if fo.BypassDocumentValidation != nil && *fo.BypassDocumentValidation {
		op = op.BypassDocumentValidation(*fo.BypassDocumentValidation)
	}
	if fo.Collation != nil {
		op = op.Collation(bsoncore.Document(fo.Collation.ToDocument()))
	}
	if fo.MaxTime != nil {
		op = op.MaxTimeMS(int64(*fo.MaxTime / time.Millisecond))
	}
	if fo.Projection != nil {
		proj, err := transformBsoncoreDocument(coll.registry, fo.Projection, true, "projection")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Fields(proj)
	}
	if fo.ReturnDocument != nil {
		op = op.NewDocument(*fo.ReturnDocument == options.After)
	}
	if fo.Sort != nil {
		sort, err := transformBsoncoreDocument(coll.registry, fo.Sort, false, "sort")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Sort(sort)
	}
	if fo.Upsert != nil {
		op = op.Upsert(*fo.Upsert)
	}
	if fo.Hint != nil {
		hint, err := transformValue(coll.registry, fo.Hint, false, "hint")
		if err != nil {
			return &SingleResult{err: err}
		}
		op = op.Hint(hint)
	}

	return coll.findAndModify(ctx, op)
}

// Watch returns a change stream for all changes on the corresponding collection. See
// https://docs.mongodb.com/manual/changeStreams/ for more information about change streams.
//
// The Collection must be configured with read concern majority or no read concern for a change stream to be created
// successfully.
//
// The pipeline parameter must be an array of documents, each representing a pipeline stage. The pipeline cannot be
// nil but can be empty. The stage documents must all be non-nil. See https://docs.mongodb.com/manual/changeStreams/ for
// a list of pipeline stages that can be used with change streams. For a pipeline of bson.D documents, the
// mongo.Pipeline{} type can be used.
//
// The opts parameter can be used to specify options for change stream creation (see the options.ChangeStreamOptions
// documentation).
func (coll *Collection) Watch(ctx context.Context, pipeline interface{},
	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {

	csConfig := changeStreamConfig{
		readConcern:    coll.readConcern,
		readPreference: coll.readPreference,
		client:         coll.client,
		registry:       coll.registry,
		streamType:     CollectionStream,
		collectionName: coll.Name(),
		databaseName:   coll.db.Name(),
		crypt:          coll.client.cryptFLE,
	}
	return newChangeStream(ctx, csConfig, pipeline, opts...)
}

// Indexes returns an IndexView instance that can be used to perform operations on the indexes for the collection.
func (coll *Collection) Indexes() IndexView {
	return IndexView{coll: coll}
}

// Drop drops the collection on the server. This method ignores "namespace not found" errors so it is safe to drop
// a collection that does not exist on the server.
func (coll *Collection) Drop(ctx context.Context) error {
	if ctx == nil {
		ctx = context.Background()
	}

	sess := sessionFromContext(ctx)
	if sess == nil && coll.client.sessionPool != nil {
		var err error
		sess, err = session.NewClientSession(coll.client.sessionPool, coll.client.id, session.Implicit)
		if err != nil {
			return err
		}
		defer sess.EndSession()
	}

	err := coll.client.validSession(sess)
	if err != nil {
		return err
	}

	wc := coll.writeConcern
	if sess.TransactionRunning() {
		wc = nil
	}
	if !writeconcern.AckWrite(wc) {
		sess = nil
	}

	selector := makePinnedSelector(sess, coll.writeSelector)

	op := operation.NewDropCollection().
		Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
		ServerSelector(selector).ClusterClock(coll.client.clock).
		Database(coll.db.name).Collection(coll.name).
		Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).
		ServerAPI(coll.client.serverAPI)
	err = op.Execute(ctx)

	// ignore namespace not found erorrs
	driverErr, ok := err.(driver.Error)
	if !ok || (ok && !driverErr.NamespaceNotFound()) {
		return replaceErrors(err)
	}
	return nil
}

// makePinnedSelector makes a selector for a pinned session with a pinned server. Will attempt to do server selection on
// the pinned server but if that fails it will go through a list of default selectors
func makePinnedSelector(sess *session.Client, defaultSelector description.ServerSelector) description.ServerSelectorFunc {
	return func(t description.Topology, svrs []description.Server) ([]description.Server, error) {
		if sess != nil && sess.PinnedServer != nil {
			// If there is a pinned server, try to find it in the list of candidates.
			for _, candidate := range svrs {
				if candidate.Addr == sess.PinnedServer.Addr {
					return []description.Server{candidate}, nil
				}
			}

			return nil, nil
		}

		return defaultSelector.SelectServer(t, svrs)
	}
}

func makeReadPrefSelector(sess *session.Client, selector description.ServerSelector, localThreshold time.Duration) description.ServerSelectorFunc {
	if sess != nil && sess.TransactionRunning() {
		selector = description.CompositeSelector([]description.ServerSelector{
			description.ReadPrefSelector(sess.CurrentRp),
			description.LatencySelector(localThreshold),
		})
	}

	return makePinnedSelector(sess, selector)
}


text:
$(function() {

  function filter(element,what) {
      var value = $(element).val();
      value = value.toLowerCase().replace(/\b[a-z]/g, function(letter) {
          return letter.toUpperCase();
      });
      if(value == '')
          $(what+' > li').show();
      else{
          $(what+' > li:not(:contains(' + value + '))').hide();
          $(what+' > li:contains(' + value + ')').show();
      }
  };

	$('#q').keyup(function(){
      filter(this,'#contentList');
  });

});

//initilize tabs
$(document).ready(function() {

 $('#admin-content-tabs').sortable();

  var currentTab;
  var slideCount =  $('.nav-tabs').children().length + 1;
  var cloneCntr = 1;

      function block_form() {
          $(".loading").show();
          $('textarea').attr('disabled', 'disabled');
          $('input').attr('disabled', 'disabled');
          $('select').attr('disabled', 'disabled');
      }

      function unblock_form() {
          $('.loading').hide();
          $('textarea').removeAttr('disabled');
          $('input').removeAttr('disabled');
          $('select').removeAttr('disabled');
          $('.errorlist').remove();
      }

      // prepare Options Object for plugin
      var options = {
          beforeSubmit: function(form, options) {
              // return false to cancel submit
              block_form();
          },
          success: function(data) {
              if (data.hasOwnProperty('created_object_id')){
                var tabId = "tab-" + (slideCount - 1);
                $('a[href="#' + tabId + '"]').attr('data-subject', data.created_object_id);
                $("#" + tabId + " .btn-primary").hide();
                $("#" + tabId + " .newContentButton").removeClass('hidden');
                var nextContent = $("#" + tabId + " a.newContentButton");
                if(nextContent.attr('href')){
                  nextContent.attr('href', nextContent.attr('href').replace("/0/", "/"+ data.created_object_id + "/"));
                }
              }

              $(".form_ajax").show();
              unblock_form();
              setTimeout(function() {
                  $(".form_ajax").hide();
              }, 3000);
          },
          error:  function(resp) {
              unblock_form();
              $(".form_ajax_error").show();
              // render errors in form fields
              var errors = JSON.parse(resp.responseText);
              for (error in errors) {
                  var tabId = '#id_' + error.replace('None-','');
                  $(""+tabId).next().html(errors[error]);
                  //hack, you don't know which one to modify
                  $(""+tabId+(cloneCntr-1)).next().html(errors[error]);
              }
              setTimeout(function() {
                  $(".form_ajax_error").hide();
              }, 3000);
          },
      };

      $('.form-horizontal').ajaxForm(options);

    //when ever any tab is clicked this method will be call
    $("#admin-content-tabs").on("click", "a", function (e) {
        e.preventDefault();

        $(this).tab('show');
        $currentTab = $(this);
    });

  //shows the tab with passed content div id..paramter tabid indicates the div where the content resides
  function showTab(tabId) {
      $('#admin-content-tabs a[href="#' + tabId + '"]').tab('show');
  }
  //return current active tab
  function getCurrentTab() {
      return currentTab;
  }

  //this will return element from current tab
  //example : if there are two tabs having  textarea with same id or same class name then when $("#someId") whill return both the text area from both tabs
  //to take care this situation we need get the element from current tab.
  function getElement(selector) {
      var tabContentId = $currentTab.attr("href");
      return $("" + tabContentId).find("" + selector);

  }

  function removeCurrentTab() {

      var tabContentId = $currentTab.attr("href");
      $currentTab.parent().remove(); //remove li of tab
      $('#admin-content-tabs a:last').tab('show'); // Select first tab
      $(tabContentId).remove(); //remove respective tab content
  }

  //this method will register event on close icon on the tab..
  var registerCloseEvent = function () {

    $(".closeTab").click(function (e) {
        e.preventDefault();

        var r=confirm("Are you sure you want to delete this tab?");
        if (r==false){
            return;
        }
          //there are multiple elements which has .closeTab icon so close the tab whose close icon is clicked
          var tabContentId = $(this).parent().attr("href");
          $(this).parent().parent().remove(); //remove li of tab
          $('#admin-content-tabs a:last').tab('show'); // Select first tab
          $(tabContentId).remove(); //remove respective tab content

          var postUrl = $(this).data("url");

          if(postUrl){
            var jqxhr = $.post(postUrl, function(e) {
            })
            .fail(function(e) {
              alert( "Error in Performing Deletion" );
            });
          }
      });
  }

  function fixIds(elem, cntr) {
    $(elem).find("[id]").add(elem).each(function() {
        this.id = this.id.replace(/\d+$/, "") + cntr;
    })
  }

  //this method will demonstrate how to add tab dynamically
  var registerslideButtonEvent = function () {
      /* just for this demo */
      $('#newtab').click(function (e) {
          e.preventDefault();

          var tabId = "tab-" + slideCount; //this is id on tab content div where the
          slideCount = slideCount + 1; //increment slide count

          $('.nav-tabs').append('
<button class="close closeTab" type="button" >×</button>'+$(this).html()+'
');
          $('.tab-content').append('

');

          var newForm = $('#emptyform form').clone(true,true);
          fixIds(newForm, cloneCntr++);

          $("#" +  tabId).html(newForm);

          $(this).tab('show');
          showTab(tabId);
          registerCloseEvent();

          $("#" +  tabId + " form").ajaxForm(options);

      });
      registerCloseEvent(); //for preloaded slides.

  }();

    $("div.panel-body").on("keyup change", ".tab-subject", function (e) {
      e.preventDefault();
      var tabId = $(this).parents(".tab-pane").attr('id');
       $('#admin-content-tabs a[href="#' + tabId + '"] span').html(this.value);
     });

    $('#updateOrder').click(function (e) {

      var subjectlist = []
      $('#admin-content-tabs a').each(function( index) {
        subjectlist.push($(this).data('subject'));
      });
        var postUrl = $(this).data("url");

        if(postUrl){
          var jqxhr = $.post(postUrl, {subjectlist: subjectlist} , function(e) {
            alert( "Order Updated Successfully" );
          })
          .fail(function(e) {
            alert( "Error In Performing Reorder" );
          });
        }
    });
});

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace App\Providers;

use App\Services\Robot\Robot;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

/**
 * Class RobotServiceProvider
 * @package App\Providers
 */
class RobotServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Package boot method
     */
    public function boot()
    {
        $this->registerBladeExtensions();
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerFacade();
        $this->registerBindings();
    }

    /**
     * Register the vault facade without the qq having to add it to the app.php file.
     *
     * @return void
     */
    public function registerFacade()
    {

    }

    /**
     * Register service provider bindings
     */
    public function registerBindings()
    {
    	/**
    	 * QQ Binding
    	 */
        $this->app->bind(
            \App\Repositories\Frontend\Robot\QQ\QQRepositoryContract::class,
            \App\Repositories\Frontend\Robot\QQ\EloquentQQRepository::class
        );

        $this->app->bind(
            \App\Repositories\Backend\Robot\QQ\QQRepositoryContract::class,
            \App\Repositories\Backend\Robot\QQ\EloquentQQRepository::class
        );

        /**
         * WeChat Binding
         */
        $this->app->bind(
            \App\Repositories\Frontend\Robot\WeChat\WeChatRepositoryContract::class,
            \App\Repositories\Frontend\Robot\WeChat\EloquentWeChatRepository::class
        );

        $this->app->bind(
            \App\Repositories\Backend\Robot\WeChat\WeChatRepositoryContract::class,
            \App\Repositories\Backend\Robot\WeChat\EloquentWeChatRepository::class
        );
        // Replacer
    }

    /**
     * Register the blade extender to use new blade sections
     */
    protected function registerBladeExtensions()
    {

    }
}


text:
package net.something.xyz;

import org.eclipse.ceylon.compiler.java.metadata.Import;
import org.eclipse.ceylon.compiler.java.metadata.Module;

/**
 * @author Ales Justin
 */
@Module(name = "net.something.xyz",
        version = "1.0.0.Final",
        dependencies = {
                @Import(name = "org.jboss.acme",
                        version = "1.0.0.CR1",
                        optional = true),
                @Import(name = "si.alesj.ceylon",
                        version = "1.0.0.GA",
                        optional = true)
        })
public class $module_ {
}


text:
'use strict';

const socket = io()

const outputYou = document.querySelector('.output-you');
const outputBot = document.querySelector('.output-bot');

const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();

function test(){
    socket.emit('chat message', 'hola');
}

recognition.lang = 'es-ES';
recognition.interimResults = false;
recognition.maxAlternatives = 1;

document.querySelector('button').addEventListener('click', () => {
  recognition.start();
});

recognition.addEventListener('speechstart', () => {
  console.log('Speech has been detected.');
});

recognition.addEventListener('result', (e) => {
  console.log('Result has been detected.');

  let last = e.results.length - 1;
  let text = e.results[last][0].transcript;

  outputYou.textContent = text;
  console.log('Confidence: ' + e.results[0][0].confidence);
  //text = 'hola'
  socket.emit('chat message', text);
});

recognition.addEventListener('speechend', () => {
  recognition.stop();
});

recognition.addEventListener('error', (e) => {
  outputBot.textContent = 'Error: ' + e.error;
});

function synthVoice(text) {
  const synth = window.speechSynthesis;
  const utterance = new SpeechSynthesisUtterance();
  utterance.text = text;
  synth.speak(utterance);
}

socket.on('bot reply', function(replyText) {
  synthVoice(replyText);

  if(replyText == '') replyText = '(No answer...)';
  outputBot.textContent = replyText;
});


text:
namespace leveldb_env {

enum MethodID {
  kSequentialFileRead,
  kSequentialFileSkip,
  kRandomAccessFileRead,
  kWritableFileAppend,
  kWritableFileClose,
  kWritableFileFlush,
  kWritableFileSync,
  kNewSequentialFile,
  kNewRandomAccessFile,
  kNewWritableFile,
  kDeleteFile,
  kCreateDir,
  kDeleteDir,
  kGetFileSize,
  kRenameFile,
  kLockFile,
  kUnlockFile,
  kGetTestDirectory,
  kNewLogger,
  kSyncParent,
  kNumEntries
};

const char* MethodIDToString(MethodID method);

leveldb::Status MakeIOError(leveldb::Slice filename,
                            const char* message,
                            MethodID method,
                            int saved_errno);
leveldb::Status MakeIOError(leveldb::Slice filename,
                            const char* message,
                            MethodID method,
                            base::PlatformFileError error);
leveldb::Status MakeIOError(leveldb::Slice filename,
                            const char* message,
                            MethodID method);

enum ErrorParsingResult {
  METHOD_ONLY,
  METHOD_AND_PFE,
  METHOD_AND_ERRNO,
  NONE,
};

ErrorParsingResult ParseMethodAndError(const char* string,
                                       MethodID* method,
                                       int* error);
bool IndicatesDiskFull(leveldb::Status status);
std::string FilePathToString(const base::FilePath& file_path);

class UMALogger {
 public:
  virtual void RecordErrorAt(MethodID method) const = 0;
  virtual void RecordOSError(MethodID method, int saved_errno) const = 0;
  virtual void RecordOSError(MethodID method,
                             base::PlatformFileError error) const = 0;
};

class RetrierProvider {
 public:
  virtual int MaxRetryTimeMillis() const = 0;
  virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const = 0;
  virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
      MethodID method) const = 0;
};

class WriteTracker {
 public:
  virtual void DidCreateNewFile(const std::string& fname) = 0;
  virtual bool DoesDirNeedSync(const std::string& fname) = 0;
  virtual void DidSyncDir(const std::string& fname) = 0;
};

class ChromiumWritableFile : public leveldb::WritableFile {
 public:
  ChromiumWritableFile(const std::string& fname,
                       FILE* f,
                       const UMALogger* uma_logger,
                       WriteTracker* tracker);
  virtual ~ChromiumWritableFile();
  virtual leveldb::Status Append(const leveldb::Slice& data);
  virtual leveldb::Status Close();
  virtual leveldb::Status Flush();
  virtual leveldb::Status Sync();

 private:
  leveldb::Status SyncParent();

  std::string filename_;
  FILE* file_;
  const UMALogger* uma_logger_;
  WriteTracker* tracker_;
  bool is_manifest_;
  std::string parent_dir_;
};

class ChromiumEnv : public leveldb::Env,
                    public UMALogger,
                    public RetrierProvider,
                    public WriteTracker {
 public:
  ChromiumEnv();
  virtual ~ChromiumEnv();

  virtual leveldb::Status NewSequentialFile(const std::string& fname,
                                            leveldb::SequentialFile** result);
  virtual leveldb::Status NewRandomAccessFile(
      const std::string& fname,
      leveldb::RandomAccessFile** result);
  virtual leveldb::Status NewWritableFile(const std::string& fname,
                                          leveldb::WritableFile** result);
  virtual bool FileExists(const std::string& fname);
  virtual leveldb::Status GetChildren(const std::string& dir,
                                      std::vector<std::string>* result);
  virtual leveldb::Status DeleteFile(const std::string& fname);
  virtual leveldb::Status CreateDir(const std::string& name);
  virtual leveldb::Status DeleteDir(const std::string& name);
  virtual leveldb::Status GetFileSize(const std::string& fname, uint64_t* size);
  virtual leveldb::Status RenameFile(const std::string& src,
                                     const std::string& dst);
  virtual leveldb::Status LockFile(const std::string& fname,
                                   leveldb::FileLock** lock);
  virtual leveldb::Status UnlockFile(leveldb::FileLock* lock);
  virtual void Schedule(void (*function)(void*), void* arg);
  virtual void StartThread(void (*function)(void* arg), void* arg);
  virtual leveldb::Status GetTestDirectory(std::string* path);
  virtual leveldb::Status NewLogger(const std::string& fname,
                                    leveldb::Logger** result);
  virtual uint64_t NowMicros();
  virtual void SleepForMicroseconds(int micros);

 protected:
  virtual void DidCreateNewFile(const std::string& fname);
  virtual bool DoesDirNeedSync(const std::string& fname);
  virtual void DidSyncDir(const std::string& fname);

  std::string name_;

 private:
  std::map<std::string, bool> needs_sync_map_;
  base::Lock map_lock_;

  const int kMaxRetryTimeMillis;
  // BGThread() is the body of the background thread
  void BGThread();
  static void BGThreadWrapper(void* arg) {
    reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
  }

  virtual void RecordErrorAt(MethodID method) const;
  virtual void RecordOSError(MethodID method, int saved_errno) const;
  virtual void RecordOSError(MethodID method,
                             base::PlatformFileError error) const;
  void RecordOpenFilesLimit(const std::string& type);
  void RecordLockFileAncestors(int num_missing_ancestors) const;
  base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const;
  base::HistogramBase* GetMethodIOErrorHistogram() const;
  base::HistogramBase* GetMaxFDHistogram(const std::string& type) const;
  base::HistogramBase* GetLockFileAncestorHistogram() const;

  // RetrierProvider implementation.
  virtual int MaxRetryTimeMillis() const { return kMaxRetryTimeMillis; }
  virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const;
  virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
      MethodID method) const;

  base::FilePath test_directory_;

  ::base::Lock mu_;
  ::base::ConditionVariable bgsignal_;
  bool started_bgthread_;

  // Entry per Schedule() call
  struct BGItem {
    void* arg;
    void (*function)(void*);
  };
  typedef std::deque<BGItem> BGQueue;
  BGQueue queue_;
};

}  // namespace leveldb_env

#endif


text:
package br.com.sgpf.common.test.pojo;

import java.util.List;

import com.google.common.collect.Lists;
import com.openpojo.reflection.PojoClass;
import com.openpojo.reflection.impl.PojoClassFactory;
import com.openpojo.validation.Validator;
import com.openpojo.validation.ValidatorBuilder;
import com.openpojo.validation.rule.Rule;
import com.openpojo.validation.rule.impl.GetterMustExistRule;
import com.openpojo.validation.rule.impl.NoNestedClassRule;
import com.openpojo.validation.rule.impl.NoPrimitivesRule;
import com.openpojo.validation.rule.impl.NoPublicFieldsExceptStaticFinalRule;
import com.openpojo.validation.rule.impl.NoStaticExceptFinalRule;
import com.openpojo.validation.rule.impl.SerializableMustHaveSerialVersionUIDRule;
import com.openpojo.validation.rule.impl.SetterMustExistRule;
import com.openpojo.validation.rule.impl.TestClassMustBeProperlyNamedRule;
import com.openpojo.validation.test.Tester;
import com.openpojo.validation.test.impl.DefaultValuesNullTester;
import com.openpojo.validation.test.impl.GetterTester;
import com.openpojo.validation.test.impl.SetterTester;

import br.com.sgpf.common.test.pojo.rules.CustomNoFieldShadowingRule;

/**
 * Classe utilitária para teste de pojos.
 *
 * @author Sergio Puntar
 */
public class PojoTester {

	/**
	 * Regras de estrutura estritas.
	 *

	 *
Devem existir Getter e Setter para todas as propriedades;

	 *
Nenhum campo deve possuir tipo primitivo;

	 *
Não devem existir classes aninhadas;

	 *
Campos static devem ser final;

	 *
Classes Serializable devem possuir serialVersionUID definido;

	 *
Propriedades de classes superiores não devem ser redefinidas (field shadowing);

	 *
Campos public devem ser static final;

	 *
Classes de teste devem ser nomeadas de acordo com as classes testadas.

	 *

	 */
	private static final Rule[] STRICT_RULES = new Rule[] {
			new GetterMustExistRule(),
			new SetterMustExistRule(),
			new NoPrimitivesRule(),
			new NoNestedClassRule(),
			new NoStaticExceptFinalRule(),
			new SerializableMustHaveSerialVersionUIDRule(),
			new CustomNoFieldShadowingRule(),
			new NoPublicFieldsExceptStaticFinalRule(),
			new TestClassMustBeProperlyNamedRule()
		};

	/**
	 * Testes de comportamento estritas.
	 *

	 *
Getter;

	 *
Setter;

	 *
Nenhum campo deve possuir valor padrão nulo, a não ser que seja primitivo ou final.

	 *

	 */
	private static final Tester[] STRICT_TESTERS = new Tester[] {
			new SetterTester(),
			new GetterTester(),
			new DefaultValuesNullTester()
		};

	/**
	 * Regras de estrutura frouxas.
	 *

	 *
Devem existir Getter e Setter para todas as propriedades;

	 *
Não devem existir classes aninhadas;

	 *
Campos static devem ser final;

	 *
Classes Serializable devem possuir serialVersionUID definido;

	 *
Propriedades de classes superiores não devem ser redefinidas (field shadowing);

	 *
Campos public devem ser static final.

	 *

	 */
	private static final Rule[] LOOSE_RULES = new Rule[] {
			new GetterMustExistRule(),
			new SetterMustExistRule(),
			new NoNestedClassRule(),
			new NoStaticExceptFinalRule(),
			new SerializableMustHaveSerialVersionUIDRule(),
			new CustomNoFieldShadowingRule(),
			new NoPublicFieldsExceptStaticFinalRule()
		};

	/**
	 * Testes de comportamento frouxas.
	 *

	 *
Getter;

	 *
Setter.

	 *

	 */
	private static final Tester[] LOOSE_TESTERS = new Tester[] {
			new SetterTester(),
			new GetterTester()
		};

	/**
	 * Regras de estrutura para pojos com conteúdo imutável.
	 *

	 *
Devem existir Getter para todas as propriedades;

	 *
Nenhum campo deve possuir tipo primitivo;

	 *
Não devem existir classes aninhadas;

	 *
Campos static devem ser final;

	 *
Classes Serializable devem possuir serialVersionUID definido;

	 *
Propriedades de classes superiores não devem ser redefinidas (field shadowing);

	 *
Campos public devem ser static final;

	 *
Classes de teste devem ser nomeadas de acordo com as classes testadas.

	 *

	 */
	private static final Rule[] UNMUTABLE_RULES = new Rule[] {
			new GetterMustExistRule(),
			new NoPrimitivesRule(),
			new NoNestedClassRule(),
			new NoStaticExceptFinalRule(),
			new SerializableMustHaveSerialVersionUIDRule(),
			new CustomNoFieldShadowingRule(),
			new NoPublicFieldsExceptStaticFinalRule(),
			new TestClassMustBeProperlyNamedRule()
		};

	/**
	 * Testes de comportamento para pojos com conteúdo imutável.
	 *

	 *
Getter;

	 *

	 */
	private static final Tester[] UNMUTABLE_TESTERS = new Tester[] {
			new GetterTester()
		};

	private List<PojoClass> pojoClasses;

	/**
	 * Cria um Pojo tester para todas as classes em um pacote.
	 *
	 * @param packageName Nome do pacote
	 */
	public PojoTester(String packageName) {
		super();
		pojoClasses = PojoClassFactory.getPojoClasses(packageName);
	}

	/**
	 * Cria um Pojo tester para uma classe.
	 *
	 * @param clazz Classe a ser testada
	 */
	public PojoTester(Class<?> clazz) {
		super();
		pojoClasses = Lists.newArrayList(PojoClassFactory.getPojoClass(clazz));
	}

	/**
	 * Valida um Pojo utilizando determinadas regras de estrutura e testes de comportamento.
	 *
	 * @param rules Regras de estrutura a serem aplicadas
	 * @param testers Testes de comportamento a serem executados
	 */
	public void validatePojo(Rule[] rules, Tester[] testers) {
		Validator validator = ValidatorBuilder.create().with(rules).with(testers).build();
		validator.validate(pojoClasses);
	}

	/**
	 * Valida um Pojo utilizando determinados testes de comportamento.
	 *
	 * @param testers Testes de comportamento a serem executados
	 */
	public void validatePojo(Tester[] testers) {
		validatePojo(new Rule[] {},	testers);
	}

	/**
	 * Valida a estrutura e comportamento de um Pojo de modo estrito.

	 * Regras de estrutura aplicadas: {@link #STRICT_RULES}
	 * Testes de comportamento executados: {@link #STRICT_TESTERS}
	 */
	public void strictValidatePojoStructAndBehaviour() {
		validatePojo(STRICT_RULES, STRICT_TESTERS);
	}

	/**
	 * Valida a estrutura e comportamento de um Pojo de modo frouxo.

	 * Regras de estrutura aplicadas: {@link #LOOSE_RULES}
	 * Testes de comportamento executados: {@link #LOOSE_TESTERS}
	 */
	public void looseValidatePojoStructAndBehaviour() {
		validatePojo(LOOSE_RULES, LOOSE_TESTERS);
	}

	/**
	 * Valida o comportamento de um Pojo de modo estrito.

	 * Testes de comportamento executados: {@link #STRICT_TESTERS}
	 */
	public void strictValidatePojoBehaviour() {
		validatePojo(STRICT_TESTERS);
	}

	/**
	 * Valida o comportamento de um Pojo de modo frouxo.

	 * Testes de comportamento executados: {@link #LOOSE_TESTERS}
	 */
	public void looseValidatePojoBehaviour() {
		validatePojo(LOOSE_TESTERS);
	}

	/**
	 * Recupera o array de regras de estrutura estritas.

	 * {@link #STRICT_RULES}
	 *
	 * @return Array de regras de estrutura estritas.
	 */
	public static Rule[] strictRules() {
		return STRICT_RULES.clone();
	}

	/**
	 * Recupera o array de testes de comportamento estritas: {@link #STRICT_TESTERS}
	 *
	 * @return Array de testes de comportamento estritas.
	 */
	public static Tester[] strictTesters() {
		return STRICT_TESTERS.clone();
	}

	/**
	 * Recupera o array de regras de estrutura frouxas: {@link #LOOSE_RULES}
	 *
	 * @return Array de regras de estrutura frouxas.
	 */
	public static Rule[] looseRules() {
		return LOOSE_RULES.clone();
	}

	/**
	 * Recupera o array de testes de comportamento frouxas: {@link #LOOSE_TESTERS}
	 *
	 * @return Array de testes de comportamento frouxas.
	 */
	public static Tester[] looseTesters() {
		return LOOSE_TESTERS.clone();
	}

	/**
	 * Recupera o array de regras de estrutura para pojos com conteúdo imutável:
	 * {@link #UNMUTABLE_RULES}
	 *
	 * @return Array de regras de estrutura para pojos com conteúdo imutável.
	 */
	public static Rule[] unmutableRules() {
		return UNMUTABLE_RULES.clone();
	}

	/**
	 * Recupera o array de testes de comportamento para pojos com conteúdo imutável:
	 * {@link #UNMUTABLE_TESTERS}
	 *
	 * @return Array de testes de comportamento para pojos com conteúdo imutável.
	 */
	public static Tester[] unmutableTesters() {
		return UNMUTABLE_TESTERS.clone();
	}
}


text:
<?php

namespace app\assets;

use yii\web\AssetBundle;

/**
 * @author Pavel. Orlov
 * @since 2.0
 */
class DashboardAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@assets';
    public $css = [
        'css/font-awesome.min.css',
        'css/animate.min.css',
        'css/bootstrap-datetimepicker.css',
        'dist/dropzone.css',
        'css/custom.css',
    ];
    public $js = [
        'js/dropzone.js',
        'js/moment.min.js',
        'js/bootstrap-progressbar.min.js',
        'js/jquery.nicescroll.min.js',
        'js/icheck.min.js',
        'js/pace.min.js',
        'js/moment/moment.min.js',
        'js/daterangepicker.js',
        'js/custom.js',
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}


text:
<?php

namespace ZendTest\Console\TestAssets;

use Zend\Console\Adapter\AbstractAdapter;

/**
 * @group      Zend_Console
 */
class ConsoleAdapter extends AbstractAdapter
{
    public $stream;

    public $autoRewind = true;

    public $testWidth = 80;

    public $testIsUtf8 = true;

    public $writtenData = array();

    /**
     * Construct.
     *
     * @param bool $autoRewind If rewinds the stream before read the next char/line
     */
    public function __construct($autoRewind = true)
    {
        $this->autoRewind = (bool) $autoRewind;
    }

    /**
     * Read a single line from the console input
     *
     * @param int $maxLength        Maximum response length
     * @return string
     */
    public function readLine($maxLength = 2048)
    {
        if ($this->autoRewind) {
            rewind($this->stream);
        }
        $line = stream_get_line($this->stream, $maxLength, PHP_EOL);
        return rtrim($line, PHP_EOL);
    }

    /**
     * Read a single character from the console input
     *
     * @param string|null   $mask   A list of allowed chars
     * @return string
     */
    public function readChar($mask = null)
    {
        if ($this->autoRewind) {
            rewind($this->stream);
        }
        do {
            $char = fread($this->stream, 1);
        } while ("" === $char || ($mask !== null && false === strstr($mask, $char)));
        return $char;
    }

    /**
     * Force reported width for testing purposes.
     *
     * @param int $width
     * @return int
     */
    public function setTestWidth($width)
    {
        $this->testWidth = $width;
    }

    /**
     * Force reported utf8 capability.
     *
     * @param bool $isUtf8
     */
    public function setTestUtf8($isUtf8)
    {
        $this->testIsUtf8 = $isUtf8;
    }

    public function isUtf8()
    {
        return $this->testIsUtf8;
    }

    public function getWidth()
    {
        return $this->testWidth;
    }

    /**
     * Tracks exactly what data has been written
     * @param string $text
     * @param null $color
     * @param null $bgColor
     */
    public function write($text, $color = null, $bgColor = null)
    {
        $this->writtenData[] = $text;
        parent::write($text, $color, $bgColor);
    }
}


text:
if (!process.env.TOWER_ROOT) process.env.TOWER_ROOT = __dirname;

require('tower').run(process.argv);


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sujan.lms.dao.author;

import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.sujan.lms.dao.DAO;
import com.sujan.lms.entity.author.Author;
import java.io.IOException;

/**
 *
 * @author Suzn
 */
public interface AuthorDAO extends DAO<Author> {

    boolean isAuthorAvailable(Author author) throws IOException, JsonIOException, JsonSyntaxException;

}


text:
<?php

namespace onservice\services;

use onservice\services\router\RouterClass as RouterClass;
use onservice\essentials\File as File;

class Router{

	private $routesPath = null;
	private $prefix = null;
	private $routeFound = true;
	private $listMiddles = [];

	public function __construct(){
		$this->routerclass = new RouterClass();
	}

	public function corsAllowAll(){
		// set CORS to open
		header('Access-Control-Allow-Origin: *');
		header('Access-Control-Allow-Methods: *');
		header("Access-Control-Allow-Headers: *");
	}

	public function addMiddle($class){
		$this->listMiddles[] = $class;
		return $this;
	}

	public function loadLibs($dir = null){

		if(!file_exists($dir)) return false;
		$dirArray = File::findRecursive($dir);
		$this->dirArray = $dirArray;

		foreach ($this->dirArray as $key => $value) {
			$key = substr($key, 1);
			$array = explode('/', $key);

			$pathClass = $dir.$value;
				$pathClass = str_replace(DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $pathClass);

			require_once $pathClass;
		}
	}

	public function directory($dir = null){

		if($dir === null){
			$dir = getcwd().DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.'routes';
		}

		$annoArrayNew = array();

		$this->routesPath = $dir;

		if(!file_exists($dir)){
			if(!@mkdir($dir,0777,true)){
				die('RouterClass: Permission denied on create '.$dir);
			}
		}

		$dirs = File::findRecursive($dir);

		foreach ($dirs as $key => $value) {
			$info = pathinfo($value);
			$extension = $info['extension'];
			if($extension !== 'php') unset($dirs[$key]);
		}

		$this->attachRoutes($dirs);
	}

	public function group($prefix){
		$this->prefix = $prefix;
		return $this;
	}

	public function runClass($class,$method = 'index'){

		$listMiddles = null;

		if($this->routeFound === false){
			$requestPar = $this->routerclass->getRequest();
			$routeFound = $this->routerclass->runResource($class,[],$method,null,null,$listMiddles,$requestPar);
		}

	}

	public function resource($methodHTTP = null,$url,$class,$method = 'index'){

		$url = $this->prefix.$url;

		$methodRequest = isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:null;
		$methodRequest = strtolower($methodRequest);

		if(gettype($methodHTTP) === 'string'){
			$methodHTTPArray = explode(',', $methodHTTP);
		}else if(gettype($methodHTTP) === 'array'){
			$methodHTTPArray = $methodHTTP;
		}

		$allow = false;
		foreach ($methodHTTPArray as $key => $value) {
			if($methodRequest === strtolower($value) || strtolower($value) === '*'  )
				$allow = true;
		}

		if($allow === true){

			$routeFound = $this->routerclass->resource($url,$class,$method,null,null,$this->listMiddles);

			if($routeFound === false){
				$this->routeFound = false;
				return $this;
			}

			if($routeFound === true){

				$this->routeFound = true;
			}else{
				$this->routeFound = false;

			}
		}

		return $this;
	}

	public function attachRoutes($dirs = null){

		foreach ($dirs as $key => $value) {

			$isIndex = false;
			$routeRef = $key;
			$routeRef = explode('/', $routeRef);
			if( strtolower(end($routeRef)) == 'index'){
				unset($routeRef[count($routeRef)-1]);
				$isIndex = true;
			}
			$routeRef = implode('/', $routeRef);

			if( substr($value, 0,1) == '_' ) continue;

			$dirEnd = $this->routesPath.ucfirst($value);
			$dirEnd = str_replace('//', '/', $dirEnd);

			$content = file_get_contents($dirEnd);
			$content = str_replace('<?php', '', $content);
			$content = str_replace('?>', '', $content);

			$className = explode('/', $key);
			$className = end($className);
			$keyNamespace = dirname($key);
			$keyNamespace = str_replace('/', '\\', $keyNamespace);

			if($keyNamespace == '\\')$keyNamespace = "";

			$dirArray = explode(DIRECTORY_SEPARATOR, $dirEnd);
			unset($dirArray[count($dirArray)-1]);

			$currentDir = implode(DIRECTORY_SEPARATOR, $dirArray).DIRECTORY_SEPARATOR;

			$libs = $currentDir.'_class';

			$this->loadLibs($libs);

			$namespace = 'onservice\service\router\routerclass'.$keyNamespace.'';
			ob_start();
			echo 'namespace '.$namespace.';';

			echo $content;
			$content2 = ob_get_contents();
			ob_get_clean();

			eval( $content2);
			eval('$route = new \\'.$namespace.'\\'.ucfirst($className).'($this)'.';');

			$route->_dir = $currentDir;

			if($routeRef == '')$routeRef='/';

			$customRoute = false;

			if( method_exists($route, 'index') ){
				$routeFound = $this->routerclass->resource($routeRef,$route,'index',null,null,$this->listMiddles);

			}

			$mthodsArray = get_class_methods($route);

			foreach ($mthodsArray as $key => $value) {

				$method = $value;
				$r = new \ReflectionClass( $namespace.'\\'.ucfirst($className) );
				$doc = $r->getMethod($method)->getDocComment();
				preg_match_all('#@(.*?)(\*\*\/|\n)#s', $doc, $annotations);
				$annoArray = $annotations[1];

				if(is_array($annoArray) && count($annoArray)<1)
					continue;

				$annoArrayNew = [];
				foreach ($annoArray as $anKey => $anValue) {

					preg_match_all('#(.*?)\((.*)\)#s', $anValue, $annotationsMacth);

					$anName = isset($annotationsMacth[1][0])?$annotationsMacth[1][0]:null;
					$anValue = isset($annotationsMacth[2][0])?$annotationsMacth[2][0]:null;

					$annoArrayNew[$anName] = $anValue;
				}

				$customRequest = isset($annoArrayNew['request'])?$annoArrayNew['request']:null;

				$customRoute = isset($annoArrayNew['route'])?$annoArrayNew['route']:$customRoute;

				$annotationMethod = isset($annoArrayNew['method'])?trim($annoArrayNew['method']):false;
				$annotationMethod = strtolower($annotationMethod);

				$methodRequest = isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:null;

				$annotationMethod = preg_replace('/^(\'(.*)\'|"(.*)")$/', '$2$3', $annotationMethod);

				if($customRequest !== null){
					@eval('$checkRequest = ['.$customRequest.'];');
					$annotationMethod = $checkRequest[0];
					$customRoute = $checkRequest[1];
				}

				$modearray = false;
				$checkArray = '';
				if($customRoute != ''){
					if( is_string($customRoute) && strpos($customRoute, '[')!==false || is_array($customRoute)){
						$modearray = true;
						$customRoute = json_encode($customRoute,JSON_UNESCAPED_SLASHES);

					}
				}

				$annotationMethod = strtolower($annotationMethod);

				if($annotationMethod === 'any') $annotationMethod = null;

				if($modearray == true){

					@eval('$checkArray = '.$customRoute.';');

					if(is_array($checkArray))
					foreach ($checkArray as $key2 => $value2) {
						$customRouteUnique = $value2;
						if($customRouteUnique !== false){
							$customRouteUnique = trim($customRouteUnique);
							$routeRef_end = $routeRef.''.$customRouteUnique;

							$routeFound = $this->routerclass->resource($routeRef_end,$route,$method,$annoArrayNew,false,$this->listMiddles);

						}
					}
				}else{

					$customRoute = preg_replace('/^(\'(.*)\'|"(.*)")$/', '$2$3', $customRoute);

					if($customRoute !== false){
						$customRoute = trim($customRoute);
						$routeRef_end = $routeRef.''.$customRoute;

						$routeFound = $this->routerclass->resource($routeRef_end,$route,$method,$annoArrayNew,$annotationMethod,$this->listMiddles);

					}
				}

			}

		}

		// realinha para o final caso exista classe Index
		$listDirs = [];
		foreach ($dirs as $key => $value) {
			$routeRef = explode('/', $key);

			if( strtolower(end($routeRef)) == 'index'){
				$listDirs[$key] = $dirs[$key];
				unset($dirs[$key]);
			}
		}
		arsort($listDirs);
		foreach ($listDirs as $key => $value) $dirs[$key] = $value;

		// cria rota de erro quando existir o methdo de erro (error)
		foreach ($dirs as $key => $value) {
			$isIndex = false;
			$routeRef = $key;
			$routeRef = explode('/', $routeRef);
			if( strtolower(end($routeRef)) == 'index'){
				unset($routeRef[count($routeRef)-1]);
				$isIndex = true;
			}
			$routeRef = implode('/', $routeRef);

			$dirEnd = $this->routesPath.ucfirst($value);
			$dirEnd = str_replace('//', '/', $dirEnd);
			$content = file_get_contents($dirEnd);
			$content = str_replace('<?php', '', $content);
			$content = str_replace('?>', '', $content);

			$className = explode('/', $key);
			$className = end($className);
			$keyNamespace = dirname($key);
			$keyNamespace = str_replace('/', '\\', $keyNamespace);

			if($keyNamespace == '\\')$keyNamespace = "";

			$namespace = 'onservice\service\router\routerclass'.$keyNamespace.'';

			eval('$route = new \\'.$namespace.'\\'.ucfirst($className).'($this)'.';');

			if(isset($route->route)) $routeRef = $routeRef.'/'.$route->route;

			if($routeRef == '')$routeRef='/';

			if (method_exists($route, 'error')) {
				$routeFound = $this->routerclass->resource($routeRef.'/+',$route,'error');

			}

		}

	}

}


text:
module Text.RDF.RDF4H.ParserUtils(
  _parseURL, justTriples
) where

import Data.RDF.Types

import Network.URI
import Network.HTTP
import Data.Char (intToDigit)
import Data.Text.Encoding (decodeUtf8)
import qualified Data.ByteString.Char8 as B
import qualified Data.Text as T
-- import qualified Data.Map as Map
import Data.Maybe (fromMaybe)

-- | A convenience function for terminating a parse with a parse failure, using
-- the given error message as the message for the failure.
errResult :: RDF rdf => String -> Either ParseFailure rdf
errResult msg = Left (ParseFailure msg)

-- | Keep the (Just t) triples (eliminating the Nothing comments), and unbox the
-- triples, leaving a list of triples.
justTriples :: [Maybe Triple] -> [Triple]
justTriples = map (fromMaybe (error "ParserUtils.justTriples")) .
              filter (/= Nothing)

-- | Parse contents at URL into an 'RDF'.
_parseURL :: RDF rdf => (T.Text -> Either ParseFailure rdf) -> String -> IO (Either ParseFailure rdf)
_parseURL parseFunc url =
  maybe
    (return (Left (ParseFailure $ "Unable to parse URL: " ++ url)))
    doParse
    (parseURI url)
  where
    showRspCode (a, b, c) = map intToDigit [a, b, c]
    httpError resp = showRspCode (rspCode resp) ++ " " ++ rspReason resp
    doParse url' =
      simpleHTTP (request url') >>= \resp ->
        case resp of
          (Left e)    -> return (errResult $ "couldn't retrieve from URL: " ++ show url' ++ " [" ++ show e ++ "]")
          (Right res) -> case rspCode res of
                           (2, 0, 0) -> return $ parseFunc (decodeUtf8 (rspBody res))
                           _         -> return (errResult $ "couldn't retrieve from URL: " ++ httpError res)

-- | Construct HTTP GET request.
request :: URI -> HTTPRequest B.ByteString
request uri = Request { rqURI = uri,
                        rqMethod = GET,
                        rqHeaders = [Header HdrConnection "close"],
                        rqBody = B.empty }