1/**
2 * Copyright (C) 2013 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.content.Context;
21import android.content.res.Resources;
22
23import java.io.IOException;
24import java.io.InputStreamReader;
25import java.util.Formatter;
26
27/**
28 * Abstract class to support common functionality for both
29 * {@link com.android.mail.ui.HtmlConversationTemplates} and
30 * {@link com.android.mail.print.HtmlPrintTemplates}.
31 *
32 * Renders data into very simple string-substitution HTML templates.
33 *
34 * Templates should be UTF-8 encoded HTML with '%s' placeholders to be substituted upon render.
35 * Plain-jane string substitution with '%s' is slightly faster than typed substitution.
36 */
37public abstract class AbstractHtmlTemplates {
38    // TODO: refine. too expensive to iterate over cursor and pre-calculate total. so either
39    // estimate it, or defer assembly until the end when size is known (deferring increases
40    // working set size vs. estimation but is exact).
41    private static final int BUFFER_SIZE_CHARS = 64 * 1024;
42
43    protected Context mContext;
44    protected Formatter mFormatter;
45    protected StringBuilder mBuilder;
46    protected boolean mInProgress = false;
47
48    public AbstractHtmlTemplates(Context context) {
49        mContext = context;
50    }
51
52    public String emit() {
53        final String out = mFormatter.toString();
54        // release the builder memory ASAP
55        mFormatter = null;
56        mBuilder = null;
57        return out;
58    }
59
60    public void reset() {
61        mBuilder = new StringBuilder(BUFFER_SIZE_CHARS);
62        mFormatter = new Formatter(mBuilder, null /* no localization */);
63    }
64
65    protected String readTemplate(int id) throws Resources.NotFoundException {
66        final StringBuilder out = new StringBuilder();
67        InputStreamReader in = null;
68        try {
69            try {
70                in = new InputStreamReader(
71                        mContext.getResources().openRawResource(id), "UTF-8");
72                final char[] buf = new char[4096];
73                int chars;
74
75                while ((chars=in.read(buf)) > 0) {
76                    out.append(buf, 0, chars);
77                }
78
79                return out.toString();
80
81            } finally {
82                if (in != null) {
83                    in.close();
84                }
85            }
86        } catch (IOException e) {
87            throw new Resources.NotFoundException("Unable to open template id="
88                    + Integer.toHexString(id) + " exception=" + e.getMessage());
89        }
90    }
91
92    protected void append(String template, Object... args) {
93        mFormatter.format(template, args);
94    }
95}
96