text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#ifndef KUDU_TABLET_TRANSACTION_H_
#define KUDU_TABLET_TRANSACTION_H_

#include <cstddef>
#include <cstdint>
#include <mutex>
#include <string>

#include <glog/logging.h>

#include "kudu/common/common.pb.h"
#include "kudu/common/timestamp.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/consensus/consensus.pb.h"
#include "kudu/consensus/opid.pb.h"
#include "kudu/consensus/raft_consensus.h"
#include "kudu/gutil/gscoped_ptr.h"
#include "kudu/gutil/port.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/rpc/result_tracker.h"
#include "kudu/rpc/rpc_header.pb.h"
#include "kudu/tserver/tserver.pb.h"
#include "kudu/util/auto_release_pool.h"
#include "kudu/util/countdown_latch.h"
#include "kudu/util/locks.h"
#include "kudu/util/memory/arena.h"
#include "kudu/util/status.h"

namespace google {
namespace protobuf {
class Message;
}
}

namespace kudu {
namespace tablet {
class TabletReplica;
class TransactionCompletionCallback;
class TransactionState;

// All metrics associated with a Transaction.
struct TransactionMetrics {
  TransactionMetrics();
  void Reset();
  int successful_inserts;
  int successful_upserts;
  int successful_updates;
  int successful_deletes;
  uint64_t commit_wait_duration_usec;
};

// Base class for transactions.
// There are different implementations for different types (Write, AlterSchema, etc.).
// TransactionDriver implementations use Transactions along with Consensus to execute
// and replicate operations in a consensus configuration.
class Transaction {
 public:

  enum TransactionType {
    WRITE_TXN,
    ALTER_SCHEMA_TXN,
  };

  enum TraceType {
    NO_TRACE_TXNS = 0,
    TRACE_TXNS = 1
  };

  enum TransactionResult {
    COMMITTED,
    ABORTED
  };

  Transaction(TransactionState* state, consensus::DriverType type, TransactionType tx_type);

  // Returns the TransactionState for this transaction.
  virtual TransactionState* state() { return state_; }
  virtual const TransactionState* state() const { return state_; }

  // Returns whether this transaction is being executed on the leader or on a
  // replica.
  consensus::DriverType type() const { return type_; }

  // Returns this transaction's type.
  TransactionType tx_type() const { return tx_type_; }

  // Builds the ReplicateMsg for this transaction.
  virtual void NewReplicateMsg(gscoped_ptr<consensus::ReplicateMsg>* replicate_msg) = 0;

  // Executes the prepare phase of this transaction, the actual actions
  // of this phase depend on the transaction type, but usually are limited
  // to what can be done without actually changing data structures and without
  // side-effects.
  virtual Status Prepare() = 0;

  // Aborts the prepare phase.
  virtual void AbortPrepare() {}

  // Actually starts a transaction, assigning a timestamp to the transaction.
  // LEADER replicas execute this in or right after Prepare(), while FOLLOWER/LEARNER
  // replicas execute this right before the Apply() phase as the transaction's
  // timestamp is only available on the LEADER's commit message.
  // Once Started(), state might have leaked to other replicas/local log and the
  // transaction can't be cancelled without issuing an abort message.
  virtual Status Start() = 0;

  // Executes the Apply() phase of the transaction, the actual actions of
  // this phase depend on the transaction type, but usually this is the
  // method where data-structures are changed.
  virtual Status Apply(gscoped_ptr<consensus::CommitMsg>* commit_msg) = 0;

  // Executed after the transaction has been applied and the commit message has
  // been appended to the log (though it might not be durable yet), or if the
  // transaction was aborted.
  // Implementations are expected to perform cleanup on this method, the driver
  // will reply to the client after this method call returns.
  // 'result' will be either COMMITTED or ABORTED, letting implementations
  // know what was the final status of the transaction.
  virtual void Finish(TransactionResult result) {}

  // Each implementation should have its own ToString() method.
  virtual std::string ToString() const = 0;

  virtual ~Transaction() {}

 private:
  // A private version of this transaction's transaction state so that
  // we can use base TransactionState methods on destructors.
  TransactionState* state_;
  const consensus::DriverType type_;
  const TransactionType tx_type_;
};

class TransactionState {
 public:

  // Returns the request PB associated with this transaction. May be NULL if
  // the transaction's state has been reset.
  virtual const google::protobuf::Message* request() const { return NULL; }

  // Returns the response PB associated with this transaction, or NULL.
  // This will only return a non-null object for leader-side transactions.
  virtual google::protobuf::Message* response() const { return NULL; }

  // Returns whether the results of the transaction are being tracked.
  bool are_results_tracked() const {
    return result_tracker_.get() != nullptr && has_request_id();
  }

  rpc::ResultTracker* result_tracker() const { return result_tracker_.get(); }

  void SetResultTracker(const scoped_refptr<rpc::ResultTracker> result_tracker) {
    result_tracker_ = result_tracker;
  }

  // Sets the ConsensusRound for this transaction, if this transaction is
  // being executed through the consensus system.
  void set_consensus_round(const scoped_refptr<consensus::ConsensusRound>& consensus_round) {
    consensus_round_ = consensus_round;
    op_id_ = consensus_round_->id();
  }

  // Returns the ConsensusRound being used, if this transaction is being
  // executed through the consensus system or NULL if it's not.
  consensus::ConsensusRound* consensus_round() {
    return consensus_round_.get();
  }

  TabletReplica* tablet_replica() const {
    return tablet_replica_;
  }

  // Return metrics related to this transaction.
  const TransactionMetrics& metrics() const {
    return tx_metrics_;
  }

  TransactionMetrics* mutable_metrics() {
    return &tx_metrics_;
  }

  void set_completion_callback(gscoped_ptr<TransactionCompletionCallback> completion_clbk) {
    completion_clbk_.reset(completion_clbk.release());
  }

  // Returns the completion callback.
  TransactionCompletionCallback* completion_callback() {
    return DCHECK_NOTNULL(completion_clbk_.get());
  }

  // Sets a heap object to be managed by this transaction's AutoReleasePool.
  template<class T>
  T* AddToAutoReleasePool(T* t) {
    return pool_.Add(t);
  }

  // Sets an array heap object to be managed by this transaction's AutoReleasePool.
  template<class T>
  T* AddArrayToAutoReleasePool(T* t) {
    return pool_.AddArray(t);
  }

  // Return the arena associated with this transaction.
  // NOTE: this is not a thread-safe arena!
  Arena* arena() {
    return &arena_;
  }

  // Each implementation should have its own ToString() method.
  virtual std::string ToString() const = 0;

  // Sets the timestamp for the transaction
  virtual void set_timestamp(const Timestamp& timestamp) {
    // make sure we set the timestamp only once
    std::lock_guard<simple_spinlock> l(txn_state_lock_);
    DCHECK_EQ(timestamp_, Timestamp::kInvalidTimestamp);
    timestamp_ = timestamp;
  }

  Timestamp timestamp() const {
    std::lock_guard<simple_spinlock> l(txn_state_lock_);
    DCHECK(timestamp_ != Timestamp::kInvalidTimestamp);
    return timestamp_;
  }

  bool has_timestamp() const {
    std::lock_guard<simple_spinlock> l(txn_state_lock_);
    return timestamp_ != Timestamp::kInvalidTimestamp;
  }

  consensus::OpId* mutable_op_id() {
    return &op_id_;
  }

  const consensus::OpId& op_id() const {
    return op_id_;
  }

  ExternalConsistencyMode external_consistency_mode() const {
    return external_consistency_mode_;
  }

  // Returns where the transaction associated with this TransactionState had an
  // associated transaction id.
  bool has_request_id() const {
    return request_id_.has_client_id();
  }

  // Returns the request id for the transaction associated with this TransactionState.
  // Not all transactions will have a request id so users of this method should call
  // 'has_request_id()' first to make sure it is set.
  const rpc::RequestIdPB& request_id() const {
    return request_id_;
  }

 protected:
  explicit TransactionState(TabletReplica* tablet_replica);
  virtual ~TransactionState();

  TransactionMetrics tx_metrics_;

  // The TabletReplica that is coordinating this transaction.
  TabletReplica* const tablet_replica_;

  // The result tracker that will cache the result of this transaction.
  scoped_refptr<rpc::ResultTracker> result_tracker_;

  // Optional callback to be called once the transaction completes.
  gscoped_ptr<TransactionCompletionCallback> completion_clbk_;

  AutoReleasePool pool_;

  // This transaction's timestamp. Protected by txn_state_lock_.
  Timestamp timestamp_;

  // The clock error when timestamp_ was read.
  uint64_t timestamp_error_;

  Arena arena_;

  // This OpId stores the canonical "anchor" OpId for this transaction.
  consensus::OpId op_id_;

  // The client's id for this transaction, if there is one.
  rpc::RequestIdPB request_id_;

  scoped_refptr<consensus::ConsensusRound> consensus_round_;

  // The defined consistency mode for this transaction.
  ExternalConsistencyMode external_consistency_mode_;

  // Lock that protects access to transaction state.
  mutable simple_spinlock txn_state_lock_;
};

// A parent class for the callback that gets called when transactions
// complete.
//
// This must be set in the TransactionState if the transaction initiator is to
// be notified of when a transaction completes. The callback belongs to the
// transaction context and is deleted along with it.
//
// NOTE: this is a concrete class so that we can use it as a default implementation
// which avoids callers having to keep checking for NULL.
class TransactionCompletionCallback {
 public:

  TransactionCompletionCallback();

  // Allows to set an error for this transaction and a mapping to a server level code.
  // Calling this method does not mean the transaction is completed.
  void set_error(const Status& status, tserver::TabletServerErrorPB::Code code);

  void set_error(const Status& status);

  bool has_error() const;

  const Status& status() const;

  const tserver::TabletServerErrorPB::Code error_code() const;

  // Subclasses should override this.
  virtual void TransactionCompleted();

  virtual ~TransactionCompletionCallback();

 protected:
  Status status_;
  tserver::TabletServerErrorPB::Code code_;
};

// TransactionCompletionCallback implementation that can be waited on.
// Helper to make async transactions, sync.
// This is templated to accept any response PB that has a TabletServerError
// 'error' field and to set the error before performing the latch countdown.
// The callback does *not* take ownership of either latch or response.
template<class ResponsePB>
class LatchTransactionCompletionCallback : public TransactionCompletionCallback {
 public:
  explicit LatchTransactionCompletionCallback(CountDownLatch* latch,
                                              ResponsePB* response)
    : latch_(DCHECK_NOTNULL(latch)),
      response_(DCHECK_NOTNULL(response)) {
  }

  virtual void TransactionCompleted() OVERRIDE {
    if (!status_.ok()) {
      StatusToPB(status_, response_->mutable_error()->mutable_status());
    }
    latch_->CountDown();
  }

 private:
  CountDownLatch* latch_;
  ResponsePB* response_;
};

}  // namespace tablet
}  // namespace kudu

#endif /* KUDU_TABLET_TRANSACTION_H_ */


text:
title: Declarative Definition
page_title: Declarative Definition - RadGrid
description: Check our Web Forms article about Declarative Definition.
slug: grid/functionality/grouping/group-by-expressions/declarative-definition
tags: declarative,definition
published: True
position: 0
---

# Declarative Definition

Each **GridTableView** object has a **GroupByExpressions** property. **GroupByExpressions** is a collection of group expressions (**GridGroupByExpression** objects).

Adding a **GridGroupByExpression** object to this collection makes the current tableview display the items divided into groups and sorted. At the top of each group of items is a **GridGroupHeaderItem**, which can display information about the common properties of the group items or aggregate values that summarize the items in the group.

## GridGroupByExpression object

Each **GridGroupByExpression** object contains two collections in turn:

* The **SelectFields** collection determines the information that is displayed in the group header.

* The **GroupByFields** collection determines the field values that are used to group the data.

Both the **SelectFields** and the **GroupByFields** collections are collections of **GridGroupByField** objects. Each **GridGroupByField** object has the following properties:

* **FieldName** specifies the name of a field in the data source. If the **GridGroupByField** is in the **SelectFields** collection, this is the field whose value (or aggregated value) is shown in the group header. If the **GridGroupByField** is in the **GroupByFields** collection, this is the field that is used to group values. Meaningful for items from the **SelectFields/GroupByFields** collections.

* **FieldAlias** specifies an alias for representing the field's name. This appears as the name of the group in the group header and in the group panel, unless the **HeaderText** property is set. The **FieldAlias** value cannot contain blanks or reserved characters such as ",", "." and so on. Meaningful for items from the **SelectFields** collection only.

* **Aggregate** specifies a **GridAggregateFunction** value. These include "Sum", "Min", "Max", "Last", "First", "Count", and "None". **Aggregate** is used for fields in the **SelectFields** collection to specify the way to aggregate values on the field for display in the group header. Meaningful for items from the **SelectFields** collection only.If you want to display aggregated values in the group footer rather than the header, you can use [column aggregates]({%slug grid/columns/aggregates%}).

* **HeaderText** specifies the name to use for the field when it appears in the group header and in the group panel. This property lets you specify a field name that includes blanks or reserved characters. This property is only used for fields in the **SelectFields** collection. Meaningful for items from the **SelectFields* *collection only.

* **HeaderValueSeparator** specifies a string that appears in the group header between the header text and the value (or aggregated value). This property is only used for fields in the **SelectFields** collection. Meaningful for items from the **SelectFields** collection only.

* **FormatString** specifies a format string for formatting field values when they appear in the group header. This property is only used for fields in the **SelectFields** collection. Meaningful for items from the **SelectFields** collection only.

* **SortOrder** specifies how group values are sorted. Its value can be "Ascending" or "Descending". This property is only used for fields in the **GroupByFields** collection. Meaningful for items from the **GroupByFields** collection only.

>caution The default value of the **SortOrder** property is "Ascending". Setting it to "None" will not affect the order in which the group items are displayed.
>

## Setting GroupByExpressions declaratively

You can set the value of a table view's **GroupByExpressions** property declaratively to provide the grid with an initial grouping state. This property is independent of whether users can drag column headers to the group panel to change the grouping, or even whether the group panel appears in the grid.

>note In a hierarchical grid, you can set the **GroupByExpressions** property for each table in the hierarchy.
>

The following example shows the declaration of a grid with the **GroupByExpressions** property set to provide grouping in the **MasterTableView**. In this example, the ShowGroupPanel property is not set to **True**, so users cannot change the specified grouping.

````ASP.NET
<telerik:RadGrid RenderMode="Lightweight" ID="RadGrid1" runat="server" DataSourceID="SqlDataSource1" GridLines="None"
  AllowPaging="True" PageSize="5" Skin="Outlook">
  <MasterTableView DataSourceID="SqlDataSource1">
    <GroupByExpressions>
      <telerik:GridGroupByExpression>
        <SelectFields>
          <telerik:GridGroupByField FieldName="UnitPrice" HeaderText="Price" />
          <telerik:GridGroupByField FieldName="UnitsInStock" HeaderText="Units at this price"
            Aggregate="Sum" />
        </SelectFields>
        <GroupByFields>
          <telerik:GridGroupByField FieldName="UnitPrice" SortOrder="Descending" />
        </GroupByFields>
      </telerik:GridGroupByExpression>
    </GroupByExpressions>
  </MasterTableView>
</telerik:RadGrid>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
          SelectCommand="SELECT [ProductName], [QuantityPerUnit], [UnitPrice], [UnitsInStock] FROM [Products]">
</asp:SqlDataSource>
````

![](images/grd_GroupByExpressions.png)

For a live example that sets the **GroupByExpressions** property (and uses additional **GridGroupByField** properties), see [Outlook-style grouping](https://demos.telerik.com/aspnet-ajax/Grid/Examples/GroupBy/OutlookStyle/DefaultCS.aspx).

## Column group-by expressions

When the user drags a column header onto the group panel, the grid automatically adds a **GridGroupByExpression** object to the **GroupByExpressions** collection of the table view that contains the column. By default, the **GroupByExpression** has a single **GridGroupByField** in its **SelectFields** and in its **GroupByFields** collections. This **GridGroupByField** sets only the **FieldName** property (to the column's **DataField** property).

You can change this default behavior, supplying values for the **GroupByExpression** that is added when the user drags a column header to the group panel. To do this, set the **GroupByExpression** property of the column.

The value of the **GroupByExpression** property is a string that defines the grouping expression, using the following syntax:

*fieldname[ alias]/aggregate(fieldname)[ alias][, ...] Group By fieldname[ sort][, ...]*

These are the parts of the expression:

* **fieldname -** The value of the **FieldName** property of the **GridGroupByField**.

* **alias -** The value of the **FieldAlias** property of the **GridGroupByField**.

* **aggregate** - The value of the **Aggregate** property of the **GridGroupByField**.

* **sort**: "asc" to set **SortOrder** to "Ascending", "desc" to set **SortOrder** to "Descending".

The following example illustrates this syntax:

````C#
Country, City, count(ContactName) Items Group By Country, City desc
````

For this example, the resulting **GridGroupByExpression** object would be as follows:

````ASP.NET
<telerik:GridGroupByExpression>
   <SelectFields>
     <telerik:GridGroupByField FieldName="Country" />
     <telerik:GridGroupByField FieldName="City" />
     <telerik:GridGroupByField
       FieldName="ContactName"
       FieldAlias="Items"
       Aggregate="Count" />
   </SelectFields>
   <GroupByFields>
      <telerik:GridGroupByField FieldName="Country" />
     <telerik:GridGroupByField
       FieldName="City"
       SortOrder="Descending" />
   </GroupByFields>
</telerik:GridGroupByExpression>
````

>note You can only set the **GroupByExpression** property of declaratively defined columns.
>

## Template columns

When you set the **GroupByExpression** property for a **GridTemplateColumn** instance, a common problem is that **RadGrid** cannot get the value from the header text for that column and display it in the **GroupHeaderItem**. In such cases you need to use the **FieldAlias** property.

The following example illustrates how this is done. It assigns an alias of "ID" in the **GroupByExpression** property of the first template column, and an alias of "Name" in the **GroupByExpression** property of the second template column.

````ASP.NET
<telerik:RadGrid RenderMode="Lightweight" ID="RadGrid1" runat="server" DataSourceID="SqlDataSource1" AutoGenerateColumns="False"
  AllowPaging="true" ShowGroupPanel="true">
  <ClientSettings AllowDragToGroup="true" />
  <MasterTableView>
    <Columns>
      <telerik:GridTemplateColumn HeaderText="ID" GroupByExpression="CustomerID ID Group By CustomerID">
        <ItemTemplate>
          <%# Eval("CustomerID") %>
        </ItemTemplate>
      </telerik:GridTemplateColumn>
      <telerik:GridTemplateColumn HeaderText="Name" GroupByExpression="CompanyName Name Group By CompanyName">
        <ItemTemplate>
          <%# Eval("CompanyName") %>
        </ItemTemplate>
      </telerik:GridTemplateColumn>
    </Columns>
  </MasterTableView>
</telerik:RadGrid>
````

redpajama_set_name: RedPajamaGithub


text:
package com.example.android.curvedmotion;

import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

/**
 * This app shows how to move a view in a curved path between two endpoints.
 * The real work is done by PathEvaluator, which interpolates along a path
 * using Bezier control and anchor points in the path.
 *
 * Watch the associated video for this demo on the DevBytes channel of developer.android.com
 * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
 * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
 */
public class CurvedMotion extends Activity {

    private static final DecelerateInterpolator sDecelerateInterpolator =
            new DecelerateInterpolator();
    boolean mTopLeft = true;
    Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_curved_motion);

        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Capture current location of button
                final int oldLeft = mButton.getLeft();
                final int oldTop = mButton.getTop();

                // Change layout parameters of button to move it
                moveButton();

                // Add OnPreDrawListener to catch button after layout but before drawing
                mButton.getViewTreeObserver().addOnPreDrawListener(
                        new ViewTreeObserver.OnPreDrawListener() {
                            public boolean onPreDraw() {
                                mButton.getViewTreeObserver().removeOnPreDrawListener(this);

                                // Capture new location
                                int left = mButton.getLeft();
                                int top = mButton.getTop();
                                int deltaX = left - oldLeft;
                                int deltaY = top - oldTop;

                                // Set up path to new location using a B�zier spline curve
                                AnimatorPath path = new AnimatorPath();
                                path.moveTo(-deltaX, -deltaY);
                                path.curveTo(-(deltaX/2), -deltaY, 0, -deltaY/2, 0, 0);

                                // Set up the animation
                                final ObjectAnimator anim = ObjectAnimator.ofObject(
                                        CurvedMotion.this, "buttonLoc",
                                        new PathEvaluator(), path.getPoints().toArray());
                                anim.setInterpolator(sDecelerateInterpolator);
                                anim.start();
                                return true;
                            }
                        });
            }
        });
    }

    /**
     * Toggles button location on click between top-left and bottom-right
     */
    private void moveButton() {
        LayoutParams params = (LayoutParams) mButton.getLayoutParams();
        if (mTopLeft) {
            params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
            params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        } else {
            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
            params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        }
        mButton.setLayoutParams(params);
        mTopLeft = !mTopLeft;
    }

    /**
     * We need this setter to translate between the information the animator
     * produces (a new "PathPoint" describing the current animated location)
     * and the information that the button requires (an xy location). The
     * setter will be called by the ObjectAnimator given the 'buttonLoc'
     * property string.
     */
    public void setButtonLoc(PathPoint newLoc) {
        mButton.setTranslationX(newLoc.mX);
        mButton.setTranslationY(newLoc.mY);
    }

}


text:
package org.jcrom;

import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jcr.Node;
import javax.jcr.Session;

import org.jcrom.util.NodeFilter;
import org.jcrom.util.PathUtils;

/**
 * Handles lazy loading of reference lists.
 *
 * @author Olafur Gauti Gudmundsson
 * @author Nicolas Dos Santos
 */
class ReferenceListLoader extends AbstractLazyLoader {

    private static final Logger logger = Logger.getLogger(ReferenceListLoader.class.getName());

    private final Class<?> objClass;
    private final Object parentObject;
    private final String nodePath;
    private final String propertyName;
    private final int depth;
    private final NodeFilter nodeFilter;
    private final Field field;

    ReferenceListLoader(Class<?> objClass, Object parentObject, String nodePath, String propertyName, Session session, Mapper mapper, int depth, NodeFilter nodeFilter, Field field) {
        super(session, mapper);
        this.objClass = objClass;
        this.parentObject = parentObject;
        this.nodePath = nodePath;
        this.propertyName = propertyName;
        this.depth = depth;
        this.nodeFilter = nodeFilter;
        this.field = field;
    }

    @Override
    protected Object doLoadObject(Session session, Mapper mapper) throws Exception {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("Lazy loading reference list for " + nodePath + " " + propertyName);
        }
        Node node = PathUtils.getNode(nodePath, session);
        return mapper.getReferenceMapper().getReferenceList(field, propertyName, objClass, node, parentObject, depth, nodeFilter, mapper);
    }
}


text:
Monads are formally defined in a branch of mathematics called *Category Theory* and correspond to a useful functional design pattern in scala. This article aims to describe the formal definition and the relationship to scala.

We firstly define *Category*, *Functor*, *Natural Transformation* and *Monad*.

a **Category** C is

 * a set of *objects*
 * a set of *morphisms* which are relations between objects
 * a composition operator * for morphisms

The constraints on a category are:

 * every object has an identity morphism
 * the composition operator is associative

A **Functor** from Category A to Category B (A→B)

 * relates objects in A to objects in B
 * relates morphisms in A to morphisms in B

A Functor also

 * preserves identity morphisms
 * preserves composition of morphisms

Note that for category A there is an obvious identity functor 1A:A→A

A **Natural Transformation** μ

 * relates two functors F,G:A→B
 * relates each object a in A to a morphism μ(a): F(a)→G(a) in category B such that
for every morphism f:a→a' in A we have μ(a') * F(f) = G(f) * μ(a) (commutativity).

a **Monad** has

 * a functor F from Category A to Category A (endomorphic functor)
 * a natural transformation ν:1A→F
 * a natural transformation μ:FxF→F
 * μ is associative with F (μ * Fμ = μ * μF)
 * ν is the effective inverse of μ  (μ * Fν = μ * νF = 1F)

###Examples in Scala
####Category
objects = Scala Types (Int,String,List[String],..), morphisms = functions between types

####Functor
*ToList: Types->Types* given by *ToList(t)=List[t] for t in Types*, maps morphisms obviously

####Monad:
 * functor=*ToList*,
 * *ν(t)=List[t]*, inserts value into a singleton list
 * *μ(t,t)=+*, concatenation of two lists

 ```scala
 trait Monad[M[_]] {
  def flatMap[A, B](x: M[A], f: A => M[B]): M[B]
  def point[A](x: A): M[A]
  def map[A, B](x: M[A], f: A => B): M[B] = flatMap(x, a => point(f(a)))
}
```

Now give me one property or theorem of monads in general and its application to the Category of types and functions in Scala.