View Javadoc
1   package org.synchronoss.cpo.core;
2   
3   /*-
4    * [[
5    * core
6    * ==
7    * Copyright (C) 2003 - 2026 Exaxis LLC, Synchronoss Technologies Inc
8    * ==
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ]]
23   */
24  
25  import java.io.Serializable;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.List;
30  
31  /**
32   * The clauses of a {@link CpoAdapter} operation: the function group to run plus any run-time where
33   * constraints, orderings, and native expressions. A CpoQuery replaces the telescoping method
34   * overloads that previously carried these as positional parameters.
35   *
36   * <p>Instances are immutable — every accumulator returns a new CpoQuery — so a query may be built
37   * once, held in a constant, and shared freely between threads:
38   *
39   * <pre>{@code
40   * Stream<ValueObject> beans =
41   *     adapter.retrieveBeans(CpoQuery.group("byDept").where(w).orderBy(ob), criteria);
42   * }</pre>
43   *
44   * @param groupName The function group name; null selects the default group
45   * @param wheres The run-time where constraints, in the order added
46   * @param orderBys The orderings, in the order added
47   * @param nativeExpressions The native expressions, in the order added
48   * @author david berry
49   */
50  public record CpoQuery(
51      String groupName,
52      List<CpoWhere> wheres,
53      List<CpoOrderBy> orderBys,
54      List<CpoNativeFunction> nativeExpressions)
55      implements Serializable {
56  
57    /** Version Id for this class. */
58    private static final long serialVersionUID = 1L;
59  
60    private static final CpoQuery DEFAULT_GROUP = new CpoQuery(null, List.of(), List.of(), List.of());
61  
62    /**
63     * A query against the named function group.
64     *
65     * @param groupName The function group name; null signifies the default group
66     * @return A CpoQuery with no clauses
67     */
68    public static CpoQuery group(String groupName) {
69      return groupName == null
70          ? DEFAULT_GROUP
71          : new CpoQuery(groupName, List.of(), List.of(), List.of());
72    }
73  
74    /**
75     * A query against the default (unnamed) function group.
76     *
77     * @return A CpoQuery with no clauses
78     */
79    public static CpoQuery defaultGroup() {
80      return DEFAULT_GROUP;
81    }
82  
83    /**
84     * Adds a where constraint.
85     *
86     * @param where The constraint to add; null is ignored
87     * @return A new CpoQuery with the constraint appended
88     */
89    public CpoQuery where(CpoWhere where) {
90      if (where == null) return this;
91      return new CpoQuery(groupName, append(wheres, where), orderBys, nativeExpressions);
92    }
93  
94    /**
95     * Adds a collection of where constraints.
96     *
97     * @param wheres The constraints to add; null or empty is ignored
98     * @return A new CpoQuery with the constraints appended
99     */
100   public CpoQuery wheres(Collection<CpoWhere> wheres) {
101     if (wheres == null || wheres.isEmpty()) return this;
102     return new CpoQuery(groupName, appendAll(this.wheres, wheres), orderBys, nativeExpressions);
103   }
104 
105   /**
106    * Adds an ordering.
107    *
108    * @param orderBy The ordering to add; null is ignored
109    * @return A new CpoQuery with the ordering appended
110    */
111   public CpoQuery orderBy(CpoOrderBy orderBy) {
112     if (orderBy == null) return this;
113     return new CpoQuery(groupName, wheres, append(orderBys, orderBy), nativeExpressions);
114   }
115 
116   /**
117    * Adds a collection of orderings.
118    *
119    * @param orderBys The orderings to add; null or empty is ignored
120    * @return A new CpoQuery with the orderings appended
121    */
122   public CpoQuery orderBys(Collection<CpoOrderBy> orderBys) {
123     if (orderBys == null || orderBys.isEmpty()) return this;
124     return new CpoQuery(groupName, wheres, appendAll(this.orderBys, orderBys), nativeExpressions);
125   }
126 
127   /**
128    * Adds a native expression that augments the expression stored in the metadata.
129    *
130    * @param nativeExpression The native expression to add; null is ignored
131    * @return A new CpoQuery with the native expression appended
132    */
133   public CpoQuery nativeExpression(CpoNativeFunction nativeExpression) {
134     if (nativeExpression == null) return this;
135     return new CpoQuery(groupName, wheres, orderBys, append(nativeExpressions, nativeExpression));
136   }
137 
138   /**
139    * Adds a collection of native expressions.
140    *
141    * @param nativeExpressions The native expressions to add; null or empty is ignored
142    * @return A new CpoQuery with the native expressions appended
143    */
144   public CpoQuery nativeExpressions(Collection<CpoNativeFunction> nativeExpressions) {
145     if (nativeExpressions == null || nativeExpressions.isEmpty()) return this;
146     return new CpoQuery(
147         groupName, wheres, orderBys, appendAll(this.nativeExpressions, nativeExpressions));
148   }
149 
150   private static <E> List<E> append(List<E> list, E element) {
151     List<E> appended = new ArrayList<>(list);
152     appended.add(element);
153     return Collections.unmodifiableList(appended);
154   }
155 
156   private static <E> List<E> appendAll(List<E> list, Collection<E> elements) {
157     List<E> appended = new ArrayList<>(list);
158     appended.addAll(elements);
159     return Collections.unmodifiableList(appended);
160   }
161 }