<commit_before>/*
 * Copyright 2012-2016 MarkLogic Corporation
 *
 * Licensed 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.
 */
package com.marklogic.client.pojo;

import com.marklogic.client.query.RawStructuredQueryDefinition;
import com.marklogic.client.query.StructuredQueryBuilder;
import com.marklogic.client.query.StructuredQueryDefinition;
import com.marklogic.client.pojo.annotation.GeospatialLatitude;
import com.marklogic.client.pojo.annotation.GeospatialLongitude;
import com.marklogic.client.pojo.annotation.GeospatialPathIndexProperty;
import com.marklogic.client.pojo.annotation.PathIndexProperty;
import com.marklogic.client.pojo.annotation.PathIndexProperty.ScalarType;
import com.marklogic.client.pojo.util.GenerateIndexConfig;
 
/** Specific to pojos yet similar to StructuredQueryBuilder, this class generates structured queries.
 * It adds convenience methods specific to working with pojos and does not replicate 
 * StructuredQueryBuilder methods that don't make sense for pojos.
 * The goal of {@link com.marklogic.client.pojo the pojo facade} is to simplify working with 
 * custom pojos. PojoQueryBuilder keeps all the powerful queries available via 
 * StructuredQueryBuilder while enabling queries across objects persisted using 
 * {@link PojoRepository}.
 *
 * <p>For methods which accept a "pojoProperty" argument we are refering to
 * properties appropriate for 
 * <a href="http://docs.oracle.com/javase/tutorial/javabeans/">JavaBeans</a>,
 * including properties accessible via public getters and setters, or public fields.</p>
 *
 *
 * <p>Where StructuredQueryBuilder accepts StructuredQueryBuilder.TextIndex as a first argument
 * to 
 * {@link StructuredQueryBuilder#value(StructuredQueryBuilder.TextIndex, String...) value(TextIndex, String...)} 
 * and 
 * {@link StructuredQueryBuilder#word(StructuredQueryBuilder.TextIndex, String...) word(TextIndex, String...)}  
 * methods,
 * PojoQueryBuilder adds shortcut methods which accept as the first argument a String name of the 
 * pojoProperty. Similarly, PojoQueryBuilder accepts String pojoProperty arguments wherever 
 * StructuredQueryBuilder accepts StructuredQueryBuilder.Element,
 * StructuredQueryBuilder.Attribute, and StructuredQueryBuilder.PathIndex
 * as arguments to 
 * {@link StructuredQueryBuilder#geoAttributePair(StructuredQueryBuilder.Element, StructuredQueryBuilder.Attribute,
 *   StructuredQueryBuilder.Attribute)
 *   geoAttributePair(Element, Attribute, Attribute)}, 
 * {@link StructuredQueryBuilder#geoElement(StructuredQueryBuilder.Element)
 *   geoElement(Element)}, 
 * {@link StructuredQueryBuilder#geoElement(StructuredQueryBuilder.Element, StructuredQueryBuilder.Element)
 *   geoElement(Element, Element)}, 
 * {@link StructuredQueryBuilder#geoElementPair(StructuredQueryBuilder.Element, StructuredQueryBuilder.Element,
 *   StructuredQueryBuilder.Element)
 *   geoElementPair(Element, Element, Element)}, 
 * {@link StructuredQueryBuilder#geoPath(StructuredQueryBuilder.PathIndex)
 *   geoPath(PathIndex)}
 * </p>
 *
 * <p>Here are a couple examples.  Without the pojo facade you might persist your products using
 * {@link com.marklogic.client.io.JacksonDatabindHandle JacksonDatabindHandle} and query the
 * json property thusly:</p>
 * <pre>{@code    StructuredQueryBuilder sqb = new StructuredQueryBuilder();
 *    QueryDefinition query = sqb.value(sqb.jsonProperty("productId"), 12345);}</pre>
 *
 * <p>If you use {@link PojoRepository} to persist your products, you can query more simply:</p>
 * <pre>{@code    PojoQueryBuilder pqb = pojoRepository.getQueryBuilder();
 *    QueryDefinition query = pqb.value("productId", 12345);}</pre>
 *
 * <p>Similarly, without the pojo facade you might persist your pojos using 
 * {@link com.marklogic.client.io.JAXBHandle JAXBHandle} and if they
 * have a geoPosition property which is an object with latitude and longitude pojoProperty's 
 * (which persist as elements) you might query them thusly:</p>
 * <pre>{@code    StructuredQueryBuilder sqb = new StructuredQueryBuilder();
 *    StructuredQueryBuilder.GeospatialIndex geoIdx = sqb.geoElementPair(
 *      sqb.element("geoPosition"), sqb.element("latitude"), sqb.element("longitude"));}</pre>
 *
 * <p>But if you use {@link PojoRepository} to persist your pojos with a latitude and longitude
 * pojoProperty's, you can query them more simply:</p>
 * <pre>{@code    PojoQueryBuilder pqb = pojoRepository.getQueryBuilder();
 *    StructuredQueryBuilder.GeospatialIndex geoIdx = 
 *      pqb.geoPair("latitude", "longitude");}</pre>
 *
 * <p>As custom pojos may have nested pojos, PojoQueryBuilder also makes it easy to query
 * those nested pojos.  For example, if you had the following classes:</p>
 * <pre>    class City {
 *     {@literal @}Id int id;
 *      Country country;
 *      int getId();
 *      void setId(int id);
 *      Country getCountry();
 *      void setCountry(Country country);
 *    }
 *    class Country {
 *      String continent;
 *      String getContinent();
 *      void setContinent();
 *    }</pre>
 *
 * <p>That is, you have a pojo class City with a property "country" of type
 * Country, you could query properties on the nested country thusly:</p>
 * <pre>{@code    PojoRepository<City, Integer> cities = 
 *      databaseClient.newPojoRepository(City.class, Integer.class);
 *    PojoQueryBuilder citiesQb = cities.getQueryBuilder();
 *    PojoQueryBuilder countriesQb = citiesQb.containerQueryBuilder("country");
 *    QueryDefinition query = countriesQb.value("continent", "EU"); }</pre>
 */
public interface PojoQueryBuilder<T> {

    /** Copied directly from  {@link com.marklogic.client.query.StructuredQueryBuilder.Operator}.
     * A comparison operator for use in range queries.
     */
    public enum Operator {
        LT, LE, GT, GE, EQ, NE;
    }

    /**
     * @param pojoProperty the property container to match against
     * @param query the query to match within the container
     * @return a query matching pojos of type T containing the pojoProperty with contents
     *          or children matching the specified query
     */
    StructuredQueryDefinition containerQuery(String pojoProperty,
        StructuredQueryDefinition query);

    /** Use this method to provide a query builder that can query a nested object within your pojo.
     * All other PojoQueryBuilder methods create queries for direct children of T which are native
     * types.  If a child of T is a pojo, and you need to query one of its children, this method
     * provides you a query builder that is specific to that child object.  To query further levels of 
     * nested objects you may use this method on the each returned PojoQueryBuilder which represents
     * one level deeper.
     * @param pojoProperty the name of a field or JavaBean property (accessed via getter or setter) on class T<commit_msg>fix a mistake in javadoc calls to containerQueryBuilder; add generics on PojoQueryBuilder<commit_after>/*
 * Copyright 2012-2016 MarkLogic Corporation
 *
 * Licensed 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.
 */
package com.marklogic.client.pojo;

import com.marklogic.client.query.RawStructuredQueryDefinition;
import com.marklogic.client.query.StructuredQueryBuilder;
import com.marklogic.client.query.StructuredQueryDefinition;
import com.marklogic.client.pojo.annotation.GeospatialLatitude;
import com.marklogic.client.pojo.annotation.GeospatialLongitude;
import com.marklogic.client.pojo.annotation.GeospatialPathIndexProperty;
import com.marklogic.client.pojo.annotation.PathIndexProperty;
import com.marklogic.client.pojo.annotation.PathIndexProperty.ScalarType;
import com.marklogic.client.pojo.util.GenerateIndexConfig;
 
/** Specific to pojos yet similar to StructuredQueryBuilder, this class generates structured queries.
 * It adds convenience methods specific to working with pojos and does not replicate 
 * StructuredQueryBuilder methods that don't make sense for pojos.
 * The goal of {@link com.marklogic.client.pojo the pojo facade} is to simplify working with 
 * custom pojos. PojoQueryBuilder keeps all the powerful queries available via 
 * StructuredQueryBuilder while enabling queries across objects persisted using 
 * {@link PojoRepository}.
 *
 * <p>For methods which accept a "pojoProperty" argument we are refering to
 * properties appropriate for 
 * <a href="http://docs.oracle.com/javase/tutorial/javabeans/">JavaBeans</a>,
 * including properties accessible via public getters and setters, or public fields.</p>
 *
 *
 * <p>Where StructuredQueryBuilder accepts StructuredQueryBuilder.TextIndex as a first argument
 * to 
 * {@link StructuredQueryBuilder#value(StructuredQueryBuilder.TextIndex, String...) value(TextIndex, String...)} 
 * and 
 * {@link StructuredQueryBuilder#word(StructuredQueryBuilder.TextIndex, String...) word(TextIndex, String...)}  
 * methods,
 * PojoQueryBuilder adds shortcut methods which accept as the first argument a String name of the 
 * pojoProperty. Similarly, PojoQueryBuilder accepts String pojoProperty arguments wherever 
 * StructuredQueryBuilder accepts StructuredQueryBuilder.Element,
 * StructuredQueryBuilder.Attribute, and StructuredQueryBuilder.PathIndex
 * as arguments to 
 * {@link StructuredQueryBuilder#geoAttributePair(StructuredQueryBuilder.Element, StructuredQueryBuilder.Attribute,
 *   StructuredQueryBuilder.Attribute)
 *   geoAttributePair(Element, Attribute, Attribute)}, 
 * {@link StructuredQueryBuilder#geoElement(StructuredQueryBuilder.Element)
 *   geoElement(Element)}, 
 * {@link StructuredQueryBuilder#geoElement(StructuredQueryBuilder.Element, StructuredQueryBuilder.Element)
 *   geoElement(Element, Element)}, 
 * {@link StructuredQueryBuilder#geoElementPair(StructuredQueryBuilder.Element, StructuredQueryBuilder.Element,
 *   StructuredQueryBuilder.Element)
 *   geoElementPair(Element, Element, Element)}, 
 * {@link StructuredQueryBuilder#geoPath(StructuredQueryBuilder.PathIndex)
 *   geoPath(PathIndex)}
 * </p>
 *
 * <p>Here are a couple examples.  Without the pojo facade you might persist your products using
 * {@link com.marklogic.client.io.JacksonDatabindHandle JacksonDatabindHandle} and query the
 * json property thusly:</p>
 * <pre>{@code    StructuredQueryBuilder sqb = new StructuredQueryBuilder();
 *    QueryDefinition query = sqb.value(sqb.jsonProperty("productId"), 12345);}</pre>
 *
 * <p>If you use {@link PojoRepository} to persist your products, you can query more simply:</p>
 * <pre>{@code    PojoQueryBuilder pqb = pojoRepository.getQueryBuilder();
 *    QueryDefinition query = pqb.value("productId", 12345);}</pre>
 *
 * <p>Similarly, without the pojo facade you might persist your pojos using 
 * {@link com.marklogic.client.io.JAXBHandle JAXBHandle} and if they
 * have a geoPosition property which is an object with latitude and longitude pojoProperty's 
 * (which persist as elements) you might query them thusly:</p>
 * <pre>{@code    StructuredQueryBuilder sqb = new StructuredQueryBuilder();
 *    StructuredQueryBuilder.GeospatialIndex geoIdx = sqb.geoElementPair(
 *      sqb.element("geoPosition"), sqb.element("latitude"), sqb.element("longitude"));}</pre>
 *
 * <p>But if you use {@link PojoRepository} to persist your pojos with a latitude and longitude
 * pojoProperty's, you can query them more simply:</p>
 * <pre>{@code    PojoQueryBuilder pqb = pojoRepository.getQueryBuilder();
 *    StructuredQueryBuilder.GeospatialIndex geoIdx = 
 *      pqb.geoPair("latitude", "longitude");}</pre>
 *
 * <p>As custom pojos may have nested pojos, PojoQueryBuilder also makes it easy to query
 * those nested pojos.  For example, if you had the following classes:</p>
 * <pre>    class City {
 *     {@literal @}Id int id;
 *      Country country;
 *      int getId();
 *      void setId(int id);
 *      Country getCountry();
 *      void setCountry(Country country);
 *    }
 *    class Country {
 *      String continent;
 *      String getContinent();
 *      void setContinent();
 *    }</pre>
 *
 * <p>That is, you have a pojo class City with a property "country" of type
 * Country, you could query properties on the nested country thusly:</p>
 * <pre>{@code    PojoRepository<City, Integer> cities = 
 *      databaseClient.newPojoRepository(City.class, Integer.class);
 *    PojoQueryBuilder<City> citiesQb = cities.getQueryBuilder();
 *    PojoQueryBuilder<Country> countriesQb = citiesQb.containerQueryBuilder("country", Country.class);
 *    QueryDefinition query = countriesQb.value("continent", "EU"); }</pre>
 */
public interface PojoQueryBuilder<T> {

    /** Copied directly from  {@link com.marklogic.client.query.StructuredQueryBuilder.Operator}.
     * A comparison operator for use in range queries.
     */
    public enum Operator {
        LT, LE, GT, GE, EQ, NE;
    }

    /**
     * @param pojoProperty the property container to match against
     * @param query the query to match within the container
     * @return a query matching pojos of type T containing the pojoProperty with contents
     *          or children matching the specified query
     */
    StructuredQueryDefinition containerQuery(String pojoProperty,
        StructuredQueryDefinition query);

    /** Use this method to provide a query builder that can query a nested object within your pojo.
     * All other PojoQueryBuilder methods create queries for direct children of T which are native
     * types.  If a child of T is a pojo, and you need to query one of its children, this method
     * provides you a query builder that is specific to that child object.  To query further levels of 
     * nested objects you may use this method on the each returned PojoQueryBuilder which represents
     * one level deeper.
     * @param pojoProperty the name of a field or JavaBean property (accessed via getter or setter) on class T
{'fraction_non_alphanumeric': 0.08880647336480108, 'fraction_numerical': 0.0029669588671611597, 'mean_word_length': 4.484837278106509, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6742356', 'n_tokens_mistral': 4076, 'n_tokens_neox': 3895, 'n_words': 1357}