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 
18 package com.android.mail.ui;
19 
20 import android.content.Context;
21 import android.content.res.Resources;
22 
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import 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  */
37 public 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 
AbstractHtmlTemplates(Context context)48     public AbstractHtmlTemplates(Context context) {
49         mContext = context;
50     }
51 
emit()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 
reset()60     public void reset() {
61         mBuilder = new StringBuilder(BUFFER_SIZE_CHARS);
62         mFormatter = new Formatter(mBuilder, null /* no localization */);
63     }
64 
readTemplate(int id)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 
append(String template, Object... args)92     protected void append(String template, Object... args) {
93         mFormatter.format(template, args);
94     }
95 }
96