15c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein/**
25c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Copyright (C) 2013 Google Inc.
35c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Licensed to The Android Open Source Project.
45c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *
55c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
65c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * you may not use this file except in compliance with the License.
75c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * You may obtain a copy of the License at
85c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *
95c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
105c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *
115c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
125c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
135c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * See the License for the specific language governing permissions and
155c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * limitations under the License.
165c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein */
175c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
185c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinpackage com.android.mail.ui;
195c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
205c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinimport android.content.Context;
215c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinimport android.content.res.Resources;
225c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
235c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinimport java.io.IOException;
245c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinimport java.io.InputStreamReader;
255c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinimport java.util.Formatter;
265c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
275c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein/**
285c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Abstract class to support common functionality for both
295c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * {@link com.android.mail.ui.HtmlConversationTemplates} and
305c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * {@link com.android.mail.print.HtmlPrintTemplates}.
315c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *
325c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Renders data into very simple string-substitution HTML templates.
335c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein *
345c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Templates should be UTF-8 encoded HTML with '%s' placeholders to be substituted upon render.
355c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein * Plain-jane string substitution with '%s' is slightly faster than typed substitution.
365c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein */
375c1692a5faeab220881a17a3427a8986ef874403Andrew Sappersteinpublic abstract class AbstractHtmlTemplates {
385c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    // TODO: refine. too expensive to iterate over cursor and pre-calculate total. so either
395c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    // estimate it, or defer assembly until the end when size is known (deferring increases
405c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    // working set size vs. estimation but is exact).
415c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    private static final int BUFFER_SIZE_CHARS = 64 * 1024;
425c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
435c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected Context mContext;
445c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected Formatter mFormatter;
455c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected StringBuilder mBuilder;
465c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected boolean mInProgress = false;
475c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
485c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    public AbstractHtmlTemplates(Context context) {
495c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mContext = context;
505c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
515c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
525c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    public String emit() {
535c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        final String out = mFormatter.toString();
545c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        // release the builder memory ASAP
555c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mFormatter = null;
565c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mBuilder = null;
575c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        return out;
585c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
595c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
605c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    public void reset() {
615c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mBuilder = new StringBuilder(BUFFER_SIZE_CHARS);
625c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mFormatter = new Formatter(mBuilder, null /* no localization */);
635c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
645c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
655c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected String readTemplate(int id) throws Resources.NotFoundException {
665c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        final StringBuilder out = new StringBuilder();
675c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        InputStreamReader in = null;
685c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        try {
695c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein            try {
705c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                in = new InputStreamReader(
715c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                        mContext.getResources().openRawResource(id), "UTF-8");
725c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                final char[] buf = new char[4096];
735c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                int chars;
745c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
755c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                while ((chars=in.read(buf)) > 0) {
765c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                    out.append(buf, 0, chars);
775c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                }
785c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
795c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                return out.toString();
805c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
815c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein            } finally {
825c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                if (in != null) {
835c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                    in.close();
845c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                }
855c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein            }
865c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        } catch (IOException e) {
875c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein            throw new Resources.NotFoundException("Unable to open template id="
885c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein                    + Integer.toHexString(id) + " exception=" + e.getMessage());
895c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        }
905c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
915c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein
925c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    protected void append(String template, Object... args) {
935c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein        mFormatter.format(template, args);
945c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein    }
955c1692a5faeab220881a17a3427a8986ef874403Andrew Sapperstein}
96