1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.print;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.text.TextUtils;
22
23/**
24 * This class encapsulates information about a document for printing
25 * purposes. This meta-data is used by the platform and print services,
26 * components that interact with printers. For example, this class
27 * contains the number of pages contained in the document it describes and
28 * this number of pages is shown to the user allowing him/her to select
29 * the range to print. Also a print service may optimize the printing
30 * process based on the content type, such as document or photo.
31 * <p>
32 * Instances of this class are created by the printing application and
33 * passed to the {@link PrintDocumentAdapter.LayoutResultCallback#onLayoutFinished(
34 * PrintDocumentInfo, boolean) PrintDocumentAdapter.LayoutResultCallback.onLayoutFinished(
35 * PrintDocumentInfo, boolean)} callback after successfully laying out the
36 * content which is performed in {@link PrintDocumentAdapter#onLayout(PrintAttributes,
37 * PrintAttributes, android.os.CancellationSignal, PrintDocumentAdapter.LayoutResultCallback,
38 * android.os.Bundle) PrintDocumentAdapter.onLayout(PrintAttributes,
39 * PrintAttributes, android.os.CancellationSignal,
40 * PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle)}.
41 * </p>
42 * <p>
43 * An example usage looks like this:
44 * <pre>
45 *
46 * . . .
47 *
48 * public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
49 *         CancellationSignal cancellationSignal, LayoutResultCallback callback,
50 *         Bundle metadata) {
51 *
52 *        // Assume the app defined a LayoutResult class which contains
53 *        // the layout result data and that the content is a document.
54 *        LayoutResult result = doSomeLayoutWork();
55 *
56 *        PrintDocumentInfo info = new PrintDocumentInfo
57 *                .Builder("printed_file.pdf")
58 *                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
59 *                .setPageCount(result.getPageCount())
60 *                .build();
61 *
62 *       callback.onLayoutFinished(info, result.getContentChanged());
63 *   }
64 *
65 *   . . .
66 *
67 * </pre>
68 * </p>
69 */
70public final class PrintDocumentInfo implements Parcelable {
71
72    /**
73     * Constant for unknown page count.
74     */
75    public static final int PAGE_COUNT_UNKNOWN = -1;
76
77    /**
78     * Content type: unknown.
79     */
80    public static final int CONTENT_TYPE_UNKNOWN = -1;
81
82    /**
83     * Content type: document.
84     * <p>
85     * A print service may use normal paper to print the content instead
86     * of dedicated photo paper. Also it may use a lower quality printing
87     * process as the content is not as sensitive to print quality variation
88     * as a photo is.
89     * </p>
90     */
91    public static final int CONTENT_TYPE_DOCUMENT = 0;
92
93    /**
94     * Content type: photo.
95     * <p>
96     * A print service may use dedicated photo paper to print the content
97     * instead of normal paper. Also it may use a higher quality printing
98     * process as the content is more sensitive to print quality variation
99     * than a document.
100     * </p>
101     */
102    public static final int CONTENT_TYPE_PHOTO = 1;
103
104    private String mName;
105    private int mPageCount;
106    private int mContentType;
107    private long mDataSize;
108
109    /**
110     * Creates a new instance.
111     */
112    private PrintDocumentInfo() {
113        /* do nothing */
114    }
115
116    /**
117     * Creates a new instance.
118     *
119     * @param Prototype from which to clone.
120     */
121    private PrintDocumentInfo(PrintDocumentInfo prototype) {
122        mName = prototype.mName;
123        mPageCount = prototype.mPageCount;
124        mContentType = prototype.mContentType;
125        mDataSize = prototype.mDataSize;
126    }
127
128    /**
129     * Creates a new instance.
130     *
131     * @param parcel Data from which to initialize.
132     */
133    private PrintDocumentInfo(Parcel parcel) {
134        mName = parcel.readString();
135        mPageCount = parcel.readInt();
136        mContentType = parcel.readInt();
137        mDataSize = parcel.readLong();
138    }
139
140    /**
141     * Gets the document name. This name may be shown to
142     * the user.
143     *
144     * @return The document name.
145     */
146    public String getName() {
147        return mName;
148    }
149
150    /**
151     * Gets the total number of pages.
152     *
153     * @return The number of pages.
154     *
155     * @see #PAGE_COUNT_UNKNOWN
156     */
157    public int getPageCount() {
158        return mPageCount;
159    }
160
161    /**
162     * Gets the content type.
163     *
164     * @return The content type.
165     *
166     * @see #CONTENT_TYPE_UNKNOWN
167     * @see #CONTENT_TYPE_DOCUMENT
168     * @see #CONTENT_TYPE_PHOTO
169     */
170    public int getContentType() {
171        return mContentType;
172    }
173
174    /**
175     * Gets the document data size in bytes.
176     *
177     * @return The data size.
178     */
179    public long getDataSize() {
180        return mDataSize;
181    }
182
183    /**
184     * Sets the document data size in bytes.
185     *
186     * @param dataSize The data size.
187     *
188     * @hide
189     */
190    public void setDataSize(long dataSize) {
191        mDataSize = dataSize;
192    }
193
194    @Override
195    public int describeContents() {
196        return 0;
197    }
198
199    @Override
200    public void writeToParcel(Parcel parcel, int flags) {
201        parcel.writeString(mName);
202        parcel.writeInt(mPageCount);
203        parcel.writeInt(mContentType);
204        parcel.writeLong(mDataSize);
205    }
206
207    @Override
208    public int hashCode() {
209        final int prime = 31;
210        int result = 1;
211        result = prime * result + ((mName != null) ? mName.hashCode() : 0);
212        result = prime * result + mContentType;
213        result = prime * result + mPageCount;
214        result = prime * result + (int) mDataSize;
215        result = prime * result + (int) mDataSize >> 32;
216        return result;
217    }
218
219    @Override
220    public boolean equals(Object obj) {
221        if (this == obj) {
222            return true;
223        }
224        if (obj == null) {
225            return false;
226        }
227        if (getClass() != obj.getClass()) {
228            return false;
229        }
230        PrintDocumentInfo other = (PrintDocumentInfo) obj;
231        if (!TextUtils.equals(mName, other.mName)) {
232            return false;
233        }
234        if (mContentType != other.mContentType) {
235            return false;
236        }
237        if (mPageCount != other.mPageCount) {
238            return false;
239        }
240        if (mDataSize != other.mDataSize) {
241            return false;
242        }
243        return true;
244    }
245
246    @Override
247    public String toString() {
248        StringBuilder builder = new StringBuilder();
249        builder.append("PrintDocumentInfo{");
250        builder.append("name=").append(mName);
251        builder.append(", pageCount=").append(mPageCount);
252        builder.append(", contentType=").append(contentTyepToString(mContentType));
253        builder.append(", dataSize=").append(mDataSize);
254        builder.append("}");
255        return builder.toString();
256    }
257
258    private String contentTyepToString(int contentType) {
259        switch (contentType) {
260            case CONTENT_TYPE_DOCUMENT: {
261                return "CONTENT_TYPE_DOCUMENT";
262            }
263            case CONTENT_TYPE_PHOTO: {
264                return "CONTENT_TYPE_PHOTO";
265            }
266            default: {
267                return "CONTENT_TYPE_UNKNOWN";
268            }
269        }
270    }
271
272    /**
273     * Builder for creating a {@link PrintDocumentInfo}.
274     */
275    public static final class Builder {
276        private final PrintDocumentInfo mPrototype;
277
278        /**
279         * Constructor.
280         *
281         * <p>
282         * The values of the relevant properties are initialized with defaults.
283         * Please refer to the documentation of the individual setters for
284         * information about the default values.
285         * </p>
286         *
287         * @param name The document name which may be shown to the user and
288         * is the file name if the content it describes is saved as a PDF.
289         * Cannot be empty.
290         */
291        public Builder(String name) {
292            if (TextUtils.isEmpty(name)) {
293                throw new IllegalArgumentException("name cannot be empty");
294            }
295            mPrototype = new PrintDocumentInfo();
296            mPrototype.mName = name;
297        }
298
299        /**
300         * Sets the total number of pages.
301         * <p>
302         * <strong>Default: </strong> {@link #PAGE_COUNT_UNKNOWN}
303         * </p>
304         *
305         * @param pageCount The number of pages. Must be greater than
306         * or equal to zero or {@link PrintDocumentInfo#PAGE_COUNT_UNKNOWN}.
307         */
308        public Builder setPageCount(int pageCount) {
309            if (pageCount < 0 && pageCount != PAGE_COUNT_UNKNOWN) {
310                throw new IllegalArgumentException("pageCount"
311                        + " must be greater than or equal to zero or"
312                        + " DocumentInfo#PAGE_COUNT_UNKNOWN");
313            }
314            mPrototype.mPageCount = pageCount;
315            return this;
316        }
317
318        /**
319         * Sets the content type.
320         * <p>
321         * <strong>Default: </strong> {@link #CONTENT_TYPE_UNKNOWN}
322         * </p>
323         *
324         * @param type The content type.
325         *
326         * @see #CONTENT_TYPE_UNKNOWN
327         * @see #CONTENT_TYPE_DOCUMENT
328         * @see #CONTENT_TYPE_PHOTO
329         */
330        public Builder setContentType(int type) {
331            mPrototype.mContentType = type;
332            return this;
333        }
334
335        /**
336         * Creates a new {@link PrintDocumentInfo} instance.
337         *
338         * @return The new instance.
339         */
340        public PrintDocumentInfo build() {
341            // Zero pages is the same as unknown as in this case
342            // we will have to ask for all pages and look a the
343            // wiritten PDF file for the page count.
344            if (mPrototype.mPageCount == 0) {
345                mPrototype.mPageCount = PAGE_COUNT_UNKNOWN;
346            }
347            return new PrintDocumentInfo(mPrototype);
348        }
349    }
350
351    public static final Parcelable.Creator<PrintDocumentInfo> CREATOR =
352            new Creator<PrintDocumentInfo>() {
353        @Override
354        public PrintDocumentInfo createFromParcel(Parcel parcel) {
355            return new PrintDocumentInfo(parcel);
356        }
357
358        @Override
359        public PrintDocumentInfo[] newArray(int size) {
360            return new PrintDocumentInfo[size];
361        }
362    };
363}
364