1 // Copyright 2010 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.api
.search
;
5 import com
.google
.appengine
.api
.search
.checkers
.FieldChecker
;
6 import com
.google
.appengine
.api
.search
.checkers
.Preconditions
;
7 import com
.google
.apphosting
.api
.search
.DocumentPb
;
9 import java
.io
.Serializable
;
10 import java
.util
.ArrayList
;
11 import java
.util
.Collections
;
12 import java
.util
.List
;
15 * Represents a document which may have been scored, possibly
16 * some computed expression fields, and a cursor to continue
20 public final class ScoredDocument
extends Document
implements Serializable
{
22 private static final long serialVersionUID
= 3062767930105951671L;
25 * A builder of scored documents. This is not thread-safe.
27 public static final class Builder
extends Document
.Builder
{
28 private final List
<Double
> scores
= new ArrayList
<Double
>();
29 private final List
<Field
> expressions
= new ArrayList
<Field
>();
30 private Cursor cursor
;
33 * Constructs a builder for a scored document.
39 * Sets the cursor to the next set of results from search.
41 * @param cursor the {@link Cursor} for the next set of results
43 * @return this builder
45 public Builder
setCursor(Cursor cursor
) {
51 * Adds the score to the builder.
53 * @param score the score to add
54 * @return this builder
56 public Builder
addScore(double score
) {
62 * Adds the expression to the builder.
64 * @param expression the expression field to add
65 * @return this builder
66 * @throws IllegalArgumentException if the expression field is invalid
68 public Builder
addExpression(Field expression
) {
69 Preconditions
.checkNotNull(expression
, "expression cannot be null");
70 expressions
.add(expression
);
75 * Builds a valid document. The builder must have set a valid document
76 * id, and have a non-empty set of valid fields.
78 * @return the scored document built by this builder
79 * @throws IllegalArgumentException if the scored document built is
83 public ScoredDocument
build() {
84 return new ScoredDocument(this);
88 private final List
<Double
> scores
;
89 private final List
<Field
> expressions
;
90 private final Cursor cursor
;
93 * Constructs a scored document with the given builder.
95 * @param builder the builder capable of building a document
97 private ScoredDocument(Builder builder
) {
99 scores
= Collections
.unmodifiableList(builder
.scores
);
100 expressions
= Collections
.unmodifiableList(builder
.expressions
);
101 cursor
= builder
.cursor
;
105 * The list of scores assigned during sort evaluation. Each sort
106 * dimension is included in this list. Positive scores are used
107 * for ascending sorts; negative scores are used for descending.
109 * @return the list of scores assigned during sort evaluation
111 public List
<Double
> getSortScores() {
116 * The list of Field which are the result of any extra expressions
117 * requested. For example, if a request contains fields to snippet or
118 * {@link FieldExpression FieldExpressions} which are named snippet
119 * expressions, then the returned expression will be a Field with the
120 * name specified in the request and HTML value set to the snippet.
122 * @return the list of Field which are the result of extra expressions
125 public List
<Field
> getExpressions() {
130 * A {@link Cursor} to be used continuing search after this search
131 * result. For this field to be populated, use
132 * {@link QueryOptions.Builder#setCursor(Cursor)}, where the cursor is
133 * created by {@code Cursor.newBuilder().setPerResult(true).build()}.
134 * Otherwise {@link #getCursor} will return null.
136 * @return a cursor used for issuing a subsequent search that
137 * will return elements beginning after this result. Can be null
139 public Cursor
getCursor() {
143 public static ScoredDocument
.Builder
newBuilder() {
144 return new ScoredDocument
.Builder();
148 * Creates a new scored document builder from the given document. All
149 * document properties are copied to the returned builder.
151 * @param document the document protocol buffer to build a scored document
153 * @return the scored document builder initialized from a document protocol
155 * @throws SearchException if a field value is invalid
157 static ScoredDocument
.Builder
newBuilder(DocumentPb
.Document document
) {
158 ScoredDocument
.Builder docBuilder
= ScoredDocument
.newBuilder();
159 docBuilder
.setId(document
.getId());
160 if (document
.hasLanguage()) {
161 docBuilder
.setLocale(FieldChecker
.parseLocale(document
.getLanguage()));
163 for (DocumentPb
.Field field
: document
.getFieldList()) {
164 docBuilder
.addField(Field
.newBuilder(field
));
166 if (document
.hasOrderId()) {
167 docBuilder
.setRank(document
.getOrderId());
173 public String
toString() {
174 return String
.format(
175 "ScoredDocument(documentId=%s, fields=%s%s, rank=%d, " +
176 "scores=%s, expressions=%s%s)",
178 Util
.iterableToString(getFields(), MAX_FIELDS_TO_STRING
),
179 Util
.fieldToString("locale", getLocale()),
181 Util
.iterableToString(scores
, 0),
182 Util
.iterableToString(expressions
, 0),
183 Util
.fieldToString("cursor", cursor
));