/*
 * Smart GWT (GWT for SmartClient)
 * Copyright 2008 and beyond, Isomorphic Software, Inc.
 *
 * Smart GWT is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.  Smart GWT is also
 * available under typical commercial license terms - see
 * http://smartclient.com/license
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */
/* sgwtgen */
 
package com.smartgwt.client.data;


import com.smartgwt.client.event.*;
import com.smartgwt.client.core.*;
import com.smartgwt.client.types.*;
import com.smartgwt.client.data.*;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.events.*;
import com.smartgwt.client.browser.window.*;
import com.smartgwt.client.rpc.*;
import com.smartgwt.client.ai.*;
import com.smartgwt.client.callbacks.*;
import com.smartgwt.client.tools.*;
import com.smartgwt.client.bean.*;
import com.smartgwt.client.widgets.*;
import com.smartgwt.client.widgets.ai.*;
import com.smartgwt.client.widgets.events.*;
import com.smartgwt.client.widgets.form.*;
import com.smartgwt.client.widgets.form.validator.*;
import com.smartgwt.client.widgets.form.fields.*;
import com.smartgwt.client.widgets.tile.*;
import com.smartgwt.client.widgets.tile.events.*;
import com.smartgwt.client.widgets.grid.*;
import com.smartgwt.client.widgets.grid.events.*;
import com.smartgwt.client.widgets.chart.*;
import com.smartgwt.client.widgets.layout.*;
import com.smartgwt.client.widgets.layout.events.*;
import com.smartgwt.client.widgets.menu.*;
import com.smartgwt.client.widgets.tour.*;
import com.smartgwt.client.widgets.notify.*;
import com.smartgwt.client.widgets.rte.*;
import com.smartgwt.client.widgets.rte.events.*;
import com.smartgwt.client.widgets.ace.*;
import com.smartgwt.client.widgets.ace.events.*;
import com.smartgwt.client.widgets.tab.*;
import com.smartgwt.client.widgets.toolbar.*;
import com.smartgwt.client.widgets.tree.*;
import com.smartgwt.client.widgets.tree.events.*;
import com.smartgwt.client.widgets.tableview.*;
import com.smartgwt.client.widgets.viewer.*;
import com.smartgwt.client.widgets.calendar.*;
import com.smartgwt.client.widgets.calendar.events.*;
import com.smartgwt.client.widgets.cube.*;
import com.smartgwt.client.widgets.notify.*;
import com.smartgwt.client.widgets.drawing.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.event.shared.*;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.core.client.JavaScriptObject;

import com.smartgwt.client.util.*;
import com.smartgwt.client.util.events.*;
import com.smartgwt.client.util.workflow.*;
import com.smartgwt.client.util.workflow.Process; // required to override java.lang.Process
import com.smartgwt.client.util.tour.*;


/**
 * A specialized subclass of {@link com.smartgwt.client.data.DSRequest} that you use to declare the properties of
 *  a subquery (a {@link com.smartgwt.client.data.Criterion#getFieldQuery fieldQuery} or 
 * {@link com.smartgwt.client.data.Criterion#getValueQuery valueQuery}) to be used in {@link
 * com.smartgwt.client.data.AdvancedCriteria}.  
 *  Subquery definitions are often very compact; only a few properties are permitted for a 
 *  client-driven subquery (see "Restrictions on client-driven subqueries", below), and many 
 *  use cases can be satisfied specifying just a 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource dataSource} and a 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getSummaryFunctions summary function}.
 *  <p>
 *  Criteria subquery definitions fall into two broad categories:<ul>
 *  <li><b>Aggregation</b>, where the subquery uses a {@link com.smartgwt.client.types.SummaryFunctionType} to aggregate
 *  or summarize a related dataset, and then filter on that aggregated or summarized value.  For
 *  example, orders with more than 10 lines, customers with an average order value more than 
 *  $1000, UK customers with an outstanding payment more than a week old, etc</li>
 *  <li><b>Related value</b>, where the subquery selects a value (or, for <code>inSet</code>-type
 *  clauses, a set of values) from a related dataSource and then filters on that value.  For 
 *  example, Products that were not ordered last month, Employees who are based in one of the 
 *  North American offices, Orders that include a particular category of Product, etc</li>
 *  </ul>
 *  <p> 
 *  In ideal circumstances - when both main and subquery {@link com.smartgwt.client.data.DataSource dataSource}s are
 *  {@link com.smartgwt.client.docs.SqlDataSource SQL DataSources}, and a number of other restrictions are 
 *  satisfied - subqueries are implemented by incorporating their functionality into a larger
 *  overall SQL query, because this is the most efficient thing to do, and gives the best 
 * performance.  See {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL} for a
 * description
 *  of the rules and nuances around this.
 *  <p>
 *  In cases where we cannot implement subqueries by embedding SQL, they are implemented by 
 *  converting the subquery definitions into separate real <code>DSRequest</code>s, executing
 *  them, and then combining their results into the wider resultset.
 *  <h3>Subquery Overview</h3>
 *  Subqueries are used to derive a value to be compared as part of the main query, from a set
 *  of related data where there is no way to directly join to a single record (usually because 
 *  the subquery is summarizing or extracting from a larger dataset).  Each subquery must 
 *  return a single value per record in the main query, because it going to be compared to a 
 *  single value from each main record (this value either comes directly from the main record,
 *  or is derived via a <code>fieldQuery</code>)
 *  <p>
 *  Because the nature of a subquery is that it is deriving a single value from multiple records,
 *  subqueries are often involved in some kind of aggregation (returning a record count, or the
 *  minimum value, for example).  While this is the most common use of subqueries, it is not
 *  the only one - see the "Simple valueQuery" example below.
 *  <p>
 *  Whether or not a subquery is aggregating multiple records, it typically needs to be 
 *  constrained by a join to the outer query.  For example, if you were looking for all customers
 *  that have placed more than $1000-worth of orders, you would use something like the 
 *  "Simple aggregating subquery" below.  As you will see, that example displays no explicit 
 *  means of joining the subquery to the outer query, and yet one is obviously necessary because
 *  we are looking for the sum of "lineValue" customer-by-customer, not the total sum for all 
 *  customers.
 *  <p>
 *  This join from the subquery to the outer query is applied implicitly by Smart GWT's SQL 
 *  engine.  It auto-discovers a Relation between the main dataSource and subquery dataSource
 *  by following {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} definitions from the subquery 
 *  dataSource, until it finds a path to the main dataSource.  This auto-discovery usually does
 *  the right thing, but there are two possibilities it does not address:<ul>
 *  <li>There is no direct or indirect Relation from the subquery dataSource to the main 
 *  dataSource.  This is an unusual case for a subquery - most use use cases call for related 
 *  dataSources - but valid cases are conceivable.  To cope with this scenario, you set 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryFK queryFK} to the special value 
 *  "<code><b>*none*</b></code>".  Note, if Smart GWT fails to find a path from the subquery
 *  dataSource to the main dataSource and <code>queryFK:"*none*"</code> has not been set, the 
 *  framework will log a warning and the fetch will fail</li>
 *  <li>There is more than one direct or indirect Relation from the subquery dataSource to the 
 *  main dataSource, and you want to use a different one from the one that was auto-discovered.
 * Again, the solution is to explicitly name the {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryFK
 * queryFK}
 *  - see the documentation for that property for details of the syntax</li>
 *  </ul>
 *  <p>
 *  Since Smart GWT can only make use of a single value as output from a subquery, if your
 *  subquery returns multiple records, we will simply use the first.  If the query returns
 *  multiple fields, you can specify the field to use as the subquery output with 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryOutput queryOutput}.  If the subquery returns more 
 *  than one field and no <code>queryOutput</code> is specified, we will use the first 
 *  aggregated ({@link com.smartgwt.client.data.AdvancedCriterionSubquery#getSummaryFunctions summaryFunction}) field, or
 *  the first {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getGroupBy grouped} field if there are no 
 *  aggregated fields, or the {@link com.smartgwt.client.data.DataSourceField#getPrimaryKey primaryKey} field if there are 
 *  also no <code>groupBy</code> fields, or just the first numeric field failing all else.  
 *  Note, however, that although we attempt to derive a sensible value, it never makes sense to
 *  return multiple records from a subquery, and it only really makes sense to return multiple 
 *  fields if you explicitly identify the correct field with <code>queryOutput</code>.  
 *  Ideally, for the sake of clarity, return a single record, and either have that record 
 *  contain a single field, or specify <code>queryOutput</code>
 *  <h4>Restrictions on client-driven subqueries</h4>
 *  For security reasons, subqueries in {@link com.smartgwt.client.data.DSRequest requests} that came from the 
 *  client-side are only permitted to specify a handful of properties.  These properties are
 *  sufficient to allow the full power of the subquery feature to be used, without allowing any
 *  of the much broader set of general properties associated with the <code>DSRequest</code>
 *  superclass.  The properties that can be set in a client-driven subquery are just those that
 *  are documented as direct properties of the <code>AdvancedCriterionSubquery</code> class - 
 *  specifically {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getCriteria criteria}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource dataSource}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getGroupBy groupBy}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getOperationId operationId}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryFK queryFK}, 
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryOutput queryOutput}, and
 *  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getSummaryFunctions summaryFunctions}
 *  <p>
 *  For <code>DSRequest</code>s that originally came from the server, it is possible to have a
 *  subquery that specifies any <code>DSRequest</code> property.  Many of these would only have
 *  any relevance or effect if the subquery was run separately rather than embedded (as 
 * described above and in the {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL} doc).  
 *  If you need to do this, look in the server Javadoc for 
 *  <code>DSRequest.setAllowArbitrarySubqueries(boolean)</code>
 *  <p>
 *  Finally, note that it is possible to switch off the ability to use subqueries altogether, 
 * either  {@link com.smartgwt.client.docs.serverds.DataSource#allowCriteriaSubqueries per-DataSource}, or globally by
 * setting 
 *  the <code>allowCriteriaSubqueries</code> flag in your <code>server.properties</code> file:<pre>
 *  allowCriteriaSubqueries: false
 *  </pre>
 *  <p>
 *  <h4><code>exists / notExists</code> operators</h4>
 *  The {@link com.smartgwt.client.types.OperatorId <code>exists / notExists</code>} operators provide a concise
 *  way to filter records based on the existence (or absence) of related rows.
 *  <p>
 *  When both main DataSource and suquery DataSource is backed by <code>SQLDataSource</code>,
 *  these operators are transformed into <code>EXISTS (...)</code> / <code>NOT EXISTS (...)</code>
 *  correlated subselects in the generated SQL. Non-SQL backends, as well as when
 * {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL:false} is set for SQL backends,
 * will
 *  execute subqueries as separate {@link com.smartgwt.client.data.DSRequest DSRequests} and apply their results manually.
 *  <p>
 *  These operators must be used with a {@link com.smartgwt.client.data.Criterion#getFieldQuery fieldQuery}:
 *  <pre>
 *  // EXISTS: at least one related row matches the subquery
 *  { operator: "exists",
 *    fieldQuery: { dataSource: "OrderLine", criteria: { /&#42 ... &#42/ } }
 *  }
 *  </pre>
 *  See full examples in the "Examples" section below.
 *  <p>
 *  <h3>Examples</h3>
 *  Subqueries are quite hard to describe in narrative text, but the following examples 
 *  demonstrate their use and should make things clearer
 *  <p>
 *  <h4>Simple aggregating subquery</h4>
 *  This example uses a <code>fieldQuery</code> to select all Order records for customer 
 *  1234, where the order total (sum of all the order line values) is greater than $1000.<pre>
 *  Order.fetchData({
 *      _constructor: "AdvancedCriteria", operator: "and", criteria: [
 *          {fieldName: "customerNumber", operator: "equals", value: 1234},
 *          {
 *               fieldQuery: {
 *                   dataSource: "OrderLine",
 *                   summaryFunctions: {lineValue: "sum"}
 *               }, operator: "greaterThan", value: 1000
 *          }
 *      ] 
 *  });
 *  </pre>
 *  <h4>Simple valueQuery</h4>
 *  This example uses a <code>valueQuery</code> to derive the employeeNumber of a manager when
 *  we only know the email address of that manager, so we can find out who reports to her.  
 *  This example shows how to use additional criteria within a subquery.  It also demonstrates 
 *  the relatively rare situation where no join to the outer dataSource is required (hence the
 *  declaration of <code>queryFK: "*none*"</code>)<pre>
 *  Employee.fetchData({
 *      _constructor: "AdvancedCriteria", operator: "and", criteria: [
 *          {
 *              fieldName: "reportsTo", 
 *              operator: "equals",
 *                  valueQuery: {
 *                      dataSource: "Employee",
 *                      queryFK: "*none*",
 *                      criteria: { operator: "and", criteria: [
 *                          {fieldName: "email", operator: "equals", value: "mpatterson@classicmodelcars.com"}
 *                      ]
 *                  }
 *              }
 *          }
 *      ]
 *  });
 *  </pre>
 *  <h4>More complex aggregation example</h4>
 *  This example uses both a <code>fieldQuery</code> and a <code>valueQuery</code> to select 
 *  all US-based customers who placed more orders in 2022 than they placed in 2021.  Note, this 
 *  is the number of orders, not the value, and the particular field that we add the "count"
 *  function to is not important (count is the same regardless of which field you count).  We
 *  chose the orderNumber in this case, but that choice is arbitrary<pre>
 *  Customer.fetchData({
 *      _constructor: "AdvancedCriteria", operator: "and", criteria: [
 *          {fieldName: "country", operator: "equals", value: "USA"},
 *          {
 *              fieldQuery: {
 *                  dataSource: "Order",
 *                  summaryFunctions : { orderNumber : "count" },
 *                  criteria: {fieldName: "orderDate", operator: "iBetweenInclusive", 
 *                                          start:new Date("2021-01-01"), end:new Date("2021-12-31")}
 *              }, 
 *              operator: "lessThan",
 *              valueQuery: {
 *                  dataSource: "Order",
 *                  summaryFunctions : { orderNumber : "count" },
 *                  criteria: {fieldName: "orderDate", operator: "iBetweenInclusive", 
 *                                          start:new Date("2022-01-01"), end:new Date("2022-12-31")}
 *              }
 *          }
 *      ]
 *  });
 *  </pre>
 *  <h4><code>exists</code> / <code>notExists</code> operators</h4>
 *  Show customers with any Orders in 2024 (exists).
 *  <pre>
 *  Customer.fetchData({
 *    _constructor: "AdvancedCriteria", operator: "and", criteria: [
 *      { operator: "exists",
 *        fieldQuery: {
 *          dataSource: "Order",
 *          criteria: { fieldName: "orderDate", operator: "iBetweenInclusive",
 *                      start: new Date("2024-01-01"), end: new Date("2024-12-31") }
 *        }
 *      }
 *    ]
 *  });
 *  </pre>
 *  Products not ordered last month (notExists).
 *  <pre>
 *  Product.fetchData({
 *    _constructor: "AdvancedCriteria", operator: "and", criteria: [
 *      { operator: "notExists",
 *        fieldQuery: {
 *          dataSource: "OrderLine",
 *          criteria: { operator: "and", criteria: [
 *            { fieldName: "orderDate", operator: "iBetweenInclusive",
 *              start: startOfLastMonth, end: endOfLastMonth }
 *          ]}
 *        }
 *      }
 *    ]
 *  });
 *  </pre>
 * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
 */
@BeanFactory.FrameworkClass
public class AdvancedCriterionSubquery extends DSRequest {

    public static AdvancedCriterionSubquery getOrCreateRef(JavaScriptObject jsObj) {
        if (jsObj == null) return null;

        final RefDataClass existingObj = RefDataClass.getRef(jsObj);

        if (existingObj instanceof AdvancedCriterionSubquery) {
            existingObj.setJsObj(jsObj);
            return (AdvancedCriterionSubquery)existingObj;
        } else

        {
            return new AdvancedCriterionSubquery(jsObj);
        }
    }
        


    public AdvancedCriterionSubquery(){
        
    }

    public AdvancedCriterionSubquery(JavaScriptObject jsObj){
        
        setJavaScriptObject(jsObj);
    }



    // ********************* Properties / Attributes ***********************

    /**
     * Indicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be
     * used to resolve the fetch request.  This property is considered as part of a set of rules we apply to decide whether a
     * subquery can be resolved by  embedding SQL (which is the most efficient thing to do, and may be significantly faster), 
     * or if we must resolve by separating the subquery out into its own {@link com.smartgwt.client.data.DSRequest}  and
     * manually applying the results. <p> There are two reasons why we might decide to run a subquery as its own
     * <code>DSRequest</code>: First, if either the "main" dataSource or the subquery dataSource is not an {@link
     * com.smartgwt.client.docs.SqlDataSource SQL dataSource}, then obviously we cannot merge into a single SQL statement. 
     * More subtly, if there is the possibility that customized logic might be in  play, we run the subquery separately because
     * in that case we may interfere with - or  completely fail to apply - the custom logic if we  do not run the subquery as a
     * full-fledged <code>DSRequest</code>.   <p> <code>canEmbedSQL</code> is intended to allow you to override our heuristics,
     * for cases  where you know a particular subquery definitely can, or definitely can't, be embedded. <p> Note, whether or
     * not we separate out the subquery into its own <code>DSRequest</code>,  {@link
     * com.smartgwt.client.docs.DeclarativeSecurity declarative security rules} are always applied.  So, for  example, if the
     * current user is not permitted to use the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource
     * subquery dataSource} or an  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getOperationId operation}
     * explicitly named on the subquery, the entire fetch operation that the subquery is part of will fail.  More nuanced, if
     * the current user is prohibited by {@link com.smartgwt.client.data.DataSourceField#getCanView field-level security} from
     * viewing a  field, that field will be stripped out of the subquery, which may lead to the subquery  failing in a
     * hard-to-predict way (but note, we always log a warning to the server logs when a field is removed in these
     * circumstances). <p> The rules around embedding or separating a subquery are, in order, as follows.   As you can see,
     * <code>canEmbedSQL</code> overrides all rules except the first (we obviously can't  embed SQL if one of the dataSources
     * isn't implemented using SQL)<ol> <li>If either the "main" dataSource or the subquery dataSource is not an {@link
     * com.smartgwt.client.docs.serverds.DataSource#serverType sql dataSource}, the subquery must by separated. 
     * Otherwise,</li> <li>If the <code>canEmbedSQL</code> flag is non-null, we honor it.  Otherwise,</li> <li>If the subquery
     * specifies an explicit operationId, the subquery must be separated.   Otherwise,</li> <li>If the subquery dataSource
     * declares a custom fetch {@link com.smartgwt.client.data.OperationBinding operation} (that is, a fetch operation that
     * does not declare an  {@link com.smartgwt.client.data.OperationBinding#getOperationId operationId}), the subquery must be
     * separated.   Otherwise,</li> <li>If the subquery dataSource declares either of the dataSource-level customization 
     * properties {@link com.smartgwt.client.data.DataSource#getServerObject DataSource.serverObject} or {@link
     * com.smartgwt.client.docs.serverds.DataSource#script DataSource.script}, the subquery must be separated.  Otherwise,</li>
     * <li>If the subquery DataSource is a direct instance of the base class (ie, its canonical class name is
     * <code>com.isomorphic.sql.SQLDataSource</code>), the subquery can be embedded. Otherwise,</li> <li>We now know that
     * subquery dataSource is a subclass of <code>SQLDataSource</code>.  We use Reflection to inspect the implementing class:
     * if it overrides any of the methods  <code>execute()</code>, <code>executeFetch{}</code> or <code>SQLExecute</code>, the
     * subquery must be separated (note, we cache the results of these tests so Reflection is only used the first time a given
     * dataSource instance is used)</li> <li>If we get to this point without having decided whether the subquery can be
     * embedded, or must be separated, the subquery can be embedded</li> </ol>
     *
     * @param canEmbedSQL New canEmbedSQL value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public AdvancedCriterionSubquery setCanEmbedSQL(Boolean canEmbedSQL) {
        return (AdvancedCriterionSubquery)setAttribute("canEmbedSQL", canEmbedSQL);
    }

    /**
     * Indicates whether this subquery can be implemented by embedding SQL directly in the wider SQL statement that will be
     * used to resolve the fetch request.  This property is considered as part of a set of rules we apply to decide whether a
     * subquery can be resolved by  embedding SQL (which is the most efficient thing to do, and may be significantly faster), 
     * or if we must resolve by separating the subquery out into its own {@link com.smartgwt.client.data.DSRequest}  and
     * manually applying the results. <p> There are two reasons why we might decide to run a subquery as its own
     * <code>DSRequest</code>: First, if either the "main" dataSource or the subquery dataSource is not an {@link
     * com.smartgwt.client.docs.SqlDataSource SQL dataSource}, then obviously we cannot merge into a single SQL statement. 
     * More subtly, if there is the possibility that customized logic might be in  play, we run the subquery separately because
     * in that case we may interfere with - or  completely fail to apply - the custom logic if we  do not run the subquery as a
     * full-fledged <code>DSRequest</code>.   <p> <code>canEmbedSQL</code> is intended to allow you to override our heuristics,
     * for cases  where you know a particular subquery definitely can, or definitely can't, be embedded. <p> Note, whether or
     * not we separate out the subquery into its own <code>DSRequest</code>,  {@link
     * com.smartgwt.client.docs.DeclarativeSecurity declarative security rules} are always applied.  So, for  example, if the
     * current user is not permitted to use the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource
     * subquery dataSource} or an  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getOperationId operation}
     * explicitly named on the subquery, the entire fetch operation that the subquery is part of will fail.  More nuanced, if
     * the current user is prohibited by {@link com.smartgwt.client.data.DataSourceField#getCanView field-level security} from
     * viewing a  field, that field will be stripped out of the subquery, which may lead to the subquery  failing in a
     * hard-to-predict way (but note, we always log a warning to the server logs when a field is removed in these
     * circumstances). <p> The rules around embedding or separating a subquery are, in order, as follows.   As you can see,
     * <code>canEmbedSQL</code> overrides all rules except the first (we obviously can't  embed SQL if one of the dataSources
     * isn't implemented using SQL)<ol> <li>If either the "main" dataSource or the subquery dataSource is not an {@link
     * com.smartgwt.client.docs.serverds.DataSource#serverType sql dataSource}, the subquery must by separated. 
     * Otherwise,</li> <li>If the <code>canEmbedSQL</code> flag is non-null, we honor it.  Otherwise,</li> <li>If the subquery
     * specifies an explicit operationId, the subquery must be separated.   Otherwise,</li> <li>If the subquery dataSource
     * declares a custom fetch {@link com.smartgwt.client.data.OperationBinding operation} (that is, a fetch operation that
     * does not declare an  {@link com.smartgwt.client.data.OperationBinding#getOperationId operationId}), the subquery must be
     * separated.   Otherwise,</li> <li>If the subquery dataSource declares either of the dataSource-level customization 
     * properties {@link com.smartgwt.client.data.DataSource#getServerObject DataSource.serverObject} or {@link
     * com.smartgwt.client.docs.serverds.DataSource#script DataSource.script}, the subquery must be separated.  Otherwise,</li>
     * <li>If the subquery DataSource is a direct instance of the base class (ie, its canonical class name is
     * <code>com.isomorphic.sql.SQLDataSource</code>), the subquery can be embedded. Otherwise,</li> <li>We now know that
     * subquery dataSource is a subclass of <code>SQLDataSource</code>.  We use Reflection to inspect the implementing class:
     * if it overrides any of the methods  <code>execute()</code>, <code>executeFetch{}</code> or <code>SQLExecute</code>, the
     * subquery must be separated (note, we cache the results of these tests so Reflection is only used the first time a given
     * dataSource instance is used)</li> <li>If we get to this point without having decided whether the subquery can be
     * embedded, or must be separated, the subquery can be embedded</li> </ol>
     *
     * @return Current canEmbedSQL value. Default value is null
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public Boolean getCanEmbedSQL()  {
        return getAttributeAsBoolean("canEmbedSQL", true);
    }
    

    /**
     * Optional criteria to use for this subquery.  Note, subqueries usually have implicit criteria, because they are joined to
     * the main dataSource fetch unless  the {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryFK queryFK} is
     * set to the special value "*none*". <p> Also, because subqueries are themselves part of a larger set of criteria, the
     * subquery  result is compared to some other value in that larger criteria - it is easy to get confused by this
     * multi-level criteria issue.  You may find it helpful to think of this property as  "inside criteria" (criteria used
     * inside this subquery to derive its result) and the criterion of which the subquery is a component (as a {@link
     * com.smartgwt.client.data.Criterion#getFieldQuery fieldQuery} or {@link com.smartgwt.client.data.Criterion#getValueQuery
     * valueQuery}), as "outside criteria"
     *
     * @param criteria New criteria value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public AdvancedCriterionSubquery setCriteria(Criteria criteria) {
        if (criteria instanceof Criterion) {
            criteria.setAttribute("_constructor", "AdvancedCriteria");
        }
        return (AdvancedCriterionSubquery)setAttribute("criteria", criteria == null ? null : criteria.getJsObj());
    }

    /**
     * Optional criteria to use for this subquery.  Note, subqueries usually have implicit criteria, because they are joined to
     * the main dataSource fetch unless  the {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getQueryFK queryFK} is
     * set to the special value "*none*". <p> Also, because subqueries are themselves part of a larger set of criteria, the
     * subquery  result is compared to some other value in that larger criteria - it is easy to get confused by this
     * multi-level criteria issue.  You may find it helpful to think of this property as  "inside criteria" (criteria used
     * inside this subquery to derive its result) and the criterion of which the subquery is a component (as a {@link
     * com.smartgwt.client.data.Criterion#getFieldQuery fieldQuery} or {@link com.smartgwt.client.data.Criterion#getValueQuery
     * valueQuery}), as "outside criteria"
     *
     * @return Current criteria value. Default value is null
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public Criteria getCriteria()  {
        return new Criteria(getAttributeAsJavaScriptObject("criteria"));
    }
    

    /**
     * The name of the {@link com.smartgwt.client.data.DataSource} to use for this subquery
     *
     * @param dataSource New dataSource value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public AdvancedCriterionSubquery setDataSource(String dataSource) {
        return (AdvancedCriterionSubquery)setAttribute("dataSource", dataSource);
    }

    /**
     * The name of the {@link com.smartgwt.client.data.DataSource} to use for this subquery
     *
     * @return Current dataSource value. Default value is null
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public String getDataSource()  {
        return getAttributeAsString("dataSource");
    }
    
    

    /**
     * {@link com.smartgwt.client.data.OperationBinding Operation binding} to use for this subquery.  Note, this refers to an
     * <code>operationBinding</code> on the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource subquery
     * dataSource}, not the DataSource associated with the overall fetch request.  Also note that specifying an
     * <code>operationId</code> will cause Smart GWT to run the subquery separately by default, which may have performance 
     * implications.  This default behavior can be overridden - see {@link
     * com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL} for details.
     *
     * @param operationId New operationId value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.Operations Operations Overview
     */
    public AdvancedCriterionSubquery setOperationId(String operationId) {
        return (AdvancedCriterionSubquery)setAttribute("operationId", operationId);
    }

    /**
     * {@link com.smartgwt.client.data.OperationBinding Operation binding} to use for this subquery.  Note, this refers to an
     * <code>operationBinding</code> on the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource subquery
     * dataSource}, not the DataSource associated with the overall fetch request.  Also note that specifying an
     * <code>operationId</code> will cause Smart GWT to run the subquery separately by default, which may have performance 
     * implications.  This default behavior can be overridden - see {@link
     * com.smartgwt.client.data.AdvancedCriterionSubquery#getCanEmbedSQL canEmbedSQL} for details.
     *
     * @return Current operationId value. Default value is null
     * @see com.smartgwt.client.docs.Operations Operations Overview
     */
    public String getOperationId()  {
        return getAttributeAsString("operationId");
    }
    

    /**
     * The default for a subquery is that the records are joined to the main DataSource on the  first {@link
     * com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} one-to-many relationship found, in field order.  So
     * for example, querying <code>Customer</code>s with a subquery on  <code>Order</code>s, we discover
     * <code>Order.customerId</code> FK pointing to  <code>Customer.id</code>.  More complicated relations are also
     * auto-discovered: for example, querying <code>Customer</code>s with a subquery on <code>OrderLine</code>s, we will
     * discover the link to <code>Customer</code> via <code>OrderLine.orderNumber</code> and then 
     * <code>Order.customerId</code>. <p> For many use cases, there is only one relation between any two DataSources, so this
     * default discovery of the relation is often sufficient.  However, if you need to, you can optionally  specify a
     * <code>queryFK</code> as the fieldName of a <code>foreignKey</code> from the "many" to  the "one".  If the relation is
     * indirect - as with the join from <code>OrderLine</code> to  <code>Customer</code> described above - you can specify
     * <code>queryFK</code> as a  dot-separated path from "many" to "one", like this:  <code>queryFK:
     * "orderNumber.customerId"</code> (but note that this is optional - often, a start point is all that is required to
     * identify the relation-path to use) <p> <b>NOTE:</b>The <code>queryFK</code> property leverages the  {@link
     * com.smartgwt.client.docs.serverds.DataSourceField#includeVia includeVia} feature, and so is constrained by the same 
     * restrictions as that feature.  Primarily, this means that <code>queryFK</code> can only name a <code>foreignKey</code>
     * field on the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource subquery dataSouce}; it is not
     * valid to name a  field on the main dataSource.  In practice, this is not usually a restriction because  typically the
     * subquery dataSource will be at the "many" end of a direct or indirect  relation to the main dataSource, and so is
     * naturally the one that declares the <code>foreignKey</code> <p> You can also specify the special value "*none*" for
     * <code>queryFK</code>, which means the  aggregation query should be done independently from the main query, to simply
     * produce a  value separately without any joins to the main dataset.  A subquery that specifies  <code>queryFK:
     * "*none*"</code> is quite unusual because most use cases of subqueries require a join to the parent dataSource; however,
     * valid use cases do exist - see the  "Simple valueQuery" example on the  {@link
     * com.smartgwt.client.data.AdvancedCriterionSubquery subquery overview page}
     *
     * @param queryFK New queryFK value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public AdvancedCriterionSubquery setQueryFK(String queryFK) {
        return (AdvancedCriterionSubquery)setAttribute("queryFK", queryFK);
    }

    /**
     * The default for a subquery is that the records are joined to the main DataSource on the  first {@link
     * com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} one-to-many relationship found, in field order.  So
     * for example, querying <code>Customer</code>s with a subquery on  <code>Order</code>s, we discover
     * <code>Order.customerId</code> FK pointing to  <code>Customer.id</code>.  More complicated relations are also
     * auto-discovered: for example, querying <code>Customer</code>s with a subquery on <code>OrderLine</code>s, we will
     * discover the link to <code>Customer</code> via <code>OrderLine.orderNumber</code> and then 
     * <code>Order.customerId</code>. <p> For many use cases, there is only one relation between any two DataSources, so this
     * default discovery of the relation is often sufficient.  However, if you need to, you can optionally  specify a
     * <code>queryFK</code> as the fieldName of a <code>foreignKey</code> from the "many" to  the "one".  If the relation is
     * indirect - as with the join from <code>OrderLine</code> to  <code>Customer</code> described above - you can specify
     * <code>queryFK</code> as a  dot-separated path from "many" to "one", like this:  <code>queryFK:
     * "orderNumber.customerId"</code> (but note that this is optional - often, a start point is all that is required to
     * identify the relation-path to use) <p> <b>NOTE:</b>The <code>queryFK</code> property leverages the  {@link
     * com.smartgwt.client.docs.serverds.DataSourceField#includeVia includeVia} feature, and so is constrained by the same 
     * restrictions as that feature.  Primarily, this means that <code>queryFK</code> can only name a <code>foreignKey</code>
     * field on the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery#getDataSource subquery dataSouce}; it is not
     * valid to name a  field on the main dataSource.  In practice, this is not usually a restriction because  typically the
     * subquery dataSource will be at the "many" end of a direct or indirect  relation to the main dataSource, and so is
     * naturally the one that declares the <code>foreignKey</code> <p> You can also specify the special value "*none*" for
     * <code>queryFK</code>, which means the  aggregation query should be done independently from the main query, to simply
     * produce a  value separately without any joins to the main dataset.  A subquery that specifies  <code>queryFK:
     * "*none*"</code> is quite unusual because most use cases of subqueries require a join to the parent dataSource; however,
     * valid use cases do exist - see the  "Simple valueQuery" example on the  {@link
     * com.smartgwt.client.data.AdvancedCriterionSubquery subquery overview page}
     *
     * @return Current queryFK value. Default value is null
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public String getQueryFK()  {
        return getAttributeAsString("queryFK");
    }
    

    /**
     * The name of the field that will be used as the output of this query.  Only useful if your subquery returns more than one
     * field, and optional even in that case.  See the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery Subqueries
     * overview} for more details
     *
     * @param queryOutput New queryOutput value. Default value is null
     * @return {@link com.smartgwt.client.data.AdvancedCriterionSubquery AdvancedCriterionSubquery} instance, for chaining setter calls
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public AdvancedCriterionSubquery setQueryOutput(String queryOutput) {
        return (AdvancedCriterionSubquery)setAttribute("queryOutput", queryOutput);
    }

    /**
     * The name of the field that will be used as the output of this query.  Only useful if your subquery returns more than one
     * field, and optional even in that case.  See the  {@link com.smartgwt.client.data.AdvancedCriterionSubquery Subqueries
     * overview} for more details
     *
     * @return Current queryOutput value. Default value is null
     * @see com.smartgwt.client.docs.AdvancedFilter Advanced Filtering
     */
    public String getQueryOutput()  {
        return getAttributeAsString("queryOutput");
    }
    
    

    // ********************* Methods ***********************

    // ********************* Static Methods ***********************

    // ***********************************************************

}
