001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.theme.bank;
021
022import java.io.File;
023import java.io.FileInputStream;
024import java.io.FileNotFoundException;
025import java.io.IOException;
026import java.io.InputStream;
027import java.io.OutputStream;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.List;
031import java.util.Map;
032import java.util.Properties;
033
034import javax.ws.rs.WebApplicationException;
035import javax.ws.rs.core.Response;
036import javax.ws.rs.core.StreamingOutput;
037
038import net.sf.json.JSONArray;
039import net.sf.json.JSONObject;
040
041import org.apache.commons.io.IOUtils;
042import org.apache.commons.logging.Log;
043import org.apache.commons.logging.LogFactory;
044import org.nuxeo.theme.presets.PaletteIdentifyException;
045import org.nuxeo.theme.presets.PaletteParseException;
046import org.nuxeo.theme.presets.PaletteParser;
047import org.nuxeo.theme.resources.BankManager;
048import org.nuxeo.theme.resources.BankUtils;
049
050public class Utils {
051    private static final Log log = LogFactory.getLog(Utils.class);
052
053    private static final List<String> PRESET_CATEGORIES = Arrays.asList("color", "background", "font", "border");
054
055    public static List<String> getCollections(String bankName) throws IOException {
056        return BankManager.getCollections(bankName);
057    }
058
059    public static List<String> getItemsInCollection(String bankName, String collection, String typeName)
060            throws IOException {
061        return BankManager.getItemsInCollection(bankName, collection, typeName);
062    }
063
064    public static List<String> listSkinsInCollection(String bankName, String collection) throws IOException {
065        Map<String, Object> info;
066        info = BankManager.getInfo(bankName, collection, "style");
067        List<String> skins = new ArrayList<String>();
068        if (info != null) {
069            for (Map.Entry<String, Object> entry : info.entrySet()) {
070                String resource = entry.getKey();
071                Map value = (Map) entry.getValue();
072                Boolean isSkin = false;
073                if (value.containsKey("skin")) {
074                    isSkin = (Boolean) value.get("skin");
075                }
076                if (isSkin) {
077                    skins.add(resource);
078                }
079            }
080        }
081        return skins;
082    }
083
084    public static Properties getPresetProperties(String bank, String collection, String category) {
085        String path = String.format("%s/%s/preset/%s", bank, collection, category);
086        File file;
087        try {
088            file = BankManager.getFile(path);
089        } catch (IOException e) {
090            throw new ThemeBankException(e.getMessage(), e);
091        }
092        Properties properties = new Properties();
093        if (!file.exists()) {
094            return properties;
095        }
096        for (File f : file.listFiles()) {
097            String content;
098            try {
099                content = BankUtils.getFileContent(f);
100            } catch (IOException e) {
101                log.warn("Could not read file: " + f.getAbsolutePath());
102                continue;
103            }
104            try {
105                properties.putAll(PaletteParser.parse(content.getBytes(), f.getName()));
106            } catch (PaletteIdentifyException e) {
107                log.warn("Could not identify palette type: " + f.getAbsolutePath());
108            } catch (PaletteParseException e) {
109                log.warn("Could not parse palette: " + f.getAbsolutePath());
110            }
111        }
112        return properties;
113    }
114
115    /*
116     * JSON calls
117     */
118    public static String listBankSkins(String bankName) throws IOException {
119        JSONArray skins = new JSONArray();
120        for (String collection : BankManager.getCollections(bankName)) {
121            Map<String, Object> info = BankManager.getInfo(bankName, collection, "style");
122            if (info == null) {
123                continue;
124            }
125            for (Map.Entry<String, Object> entry : info.entrySet()) {
126                String resource = entry.getKey();
127                Map value = (Map) entry.getValue();
128                if (value.containsKey("skin") && (Boolean) value.get("skin")) {
129                    Boolean isBase = false;
130                    if (value.containsKey("base")) {
131                        isBase = (Boolean) value.get("base");
132                    }
133                    JSONObject skinMap = new JSONObject();
134                    skinMap.put("bank", bankName);
135                    skinMap.put("collection", collection);
136                    skinMap.put("resource", resource);
137                    skinMap.put("name", String.format("%s (%s)", resource.replace(".css", ""), collection));
138                    skinMap.put("base", isBase);
139                    skins.add(skinMap);
140                }
141            }
142        }
143        return skins.toString();
144    }
145
146    public static String listBankStyles(String bankName) throws IOException {
147        JSONArray styles = new JSONArray();
148        for (String collection : BankManager.getCollections(bankName)) {
149            for (String resource : getItemsInCollection(bankName, collection, "style")) {
150                JSONObject styleMap = new JSONObject();
151                styleMap.put("bank", bankName);
152                styleMap.put("collection", collection);
153                styleMap.put("resource", resource);
154                styleMap.put("name", String.format("%s (%s)", resource.replace(".css", ""), collection));
155                styles.add(styleMap);
156            }
157        }
158        return styles.toString();
159    }
160
161    public static String listBankPresets(String bankName) throws IOException {
162        JSONArray presets = new JSONArray();
163        for (String collection : BankManager.getCollections(bankName)) {
164            for (String category : PRESET_CATEGORIES) {
165                for (Map.Entry property : getPresetProperties(bankName, collection, category).entrySet()) {
166                    JSONObject presetMap = new JSONObject();
167                    presetMap.put("bank", bankName);
168                    presetMap.put("collection", collection);
169                    presetMap.put("category", category);
170                    presetMap.put("name", property.getKey());
171                    presetMap.put("value", property.getValue());
172                    presets.add(presetMap);
173                }
174            }
175        }
176        return presets.toString();
177    }
178
179    public static String listImages(String bank) throws IOException {
180        JSONArray index = new JSONArray();
181        for (String collection : BankManager.getCollections(bank)) {
182            String path = String.format("%s/%s/image/", bank, collection);
183            File file = BankManager.getFile(path);
184            if (!file.isDirectory()) {
185                throw new IOException("Expected folder: " + path);
186            }
187            for (File image : file.listFiles()) {
188                JSONObject imageMap = new JSONObject();
189                imageMap.put("name", image.getName());
190                imageMap.put("collection", collection);
191                index.add(imageMap);
192            }
193        }
194        return index.toString();
195    }
196
197    public static String listCollections(String bank) throws IOException {
198        JSONArray index = new JSONArray();
199        for (String collection : BankManager.getCollections(bank)) {
200            index.add(collection);
201        }
202        return index.toString();
203    }
204
205    public static String getNavTree() throws IOException {
206        JSONArray tree = new JSONArray();
207
208        for (String bankName : BankManager.getBankNames()) {
209            JSONObject bankNode = new JSONObject();
210            bankNode.put("state", "open");
211
212            JSONObject bankMap = new JSONObject();
213            bankMap.put("title", bankName);
214
215            JSONObject bankAttributes = new JSONObject();
216            bankAttributes.put("rel", "bank");
217            bankAttributes.put("path", String.format("/%s", bankName));
218            bankAttributes.put("id", BankUtils.getDomId(bankName));
219            bankNode.put("attributes", bankAttributes);
220            bankNode.put("data", bankMap);
221
222            JSONArray childrenNodes = new JSONArray();
223            for (String collection : BankManager.getCollections(bankName)) {
224                childrenNodes.add(getNavTreeCollectionNode(bankName, collection));
225            }
226            bankNode.put("children", childrenNodes);
227
228            tree.add(bankNode);
229        }
230        return tree.toString();
231    }
232
233    private static JSONObject getNavTreeCollectionNode(String bankName, String collection) throws IOException {
234
235        JSONObject collectionNode = new JSONObject();
236
237        JSONObject collectionMap = new JSONObject();
238        collectionMap.put("title", collection);
239
240        JSONObject collectionAttributes = new JSONObject();
241        collectionAttributes.put("rel", "collection");
242        collectionAttributes.put("path", String.format("/%s/%s", bankName, collection));
243        collectionAttributes.put("id", BankUtils.getDomId(String.format("%s-%s", bankName, collection)));
244
245        collectionNode.put("data", collectionMap);
246        collectionNode.put("attributes", collectionAttributes);
247
248        JSONArray folderTypeNodes = new JSONArray();
249        final String[] TYPE_NAMES = { "skin", "style", "preset", "image" };
250        for (String typeName : TYPE_NAMES) {
251            JSONObject folderTypeNode = new JSONObject();
252            JSONObject folderTypeMap = new JSONObject();
253            folderTypeMap.put("title", typeName);
254
255            JSONObject folderTypeAttributes = new JSONObject();
256            folderTypeAttributes.put("rel", "folder");
257            folderTypeAttributes.put("path", String.format("/%s/%s/%s", bankName, collection, typeName));
258            folderTypeAttributes.put("id",
259                    BankUtils.getDomId(String.format("%s-%s-%s", bankName, collection, typeName)));
260
261            folderTypeNode.put("attributes", folderTypeAttributes);
262            folderTypeNode.put("data", folderTypeMap);
263
264            JSONArray items = new JSONArray();
265            List<String> skins = listSkinsInCollection(bankName, collection);
266            String effectiveTypeName = "skin".equals(typeName) ? "style" : typeName;
267            for (String item : BankManager.getItemsInCollection(bankName, collection, effectiveTypeName)) {
268
269                if ("skin".equals(typeName)) {
270                    if (!skins.contains(item)) {
271                        continue;
272                    }
273                } else if ("style".equals(typeName)) {
274                    if (skins.contains(item)) {
275                        continue;
276                    }
277                }
278                JSONObject itemNode = new JSONObject();
279                JSONObject itemMap = new JSONObject();
280                itemMap.put("title", item);
281
282                JSONObject itemAttributes = new JSONObject();
283                itemAttributes.put("rel", typeName);
284                itemAttributes.put("path", String.format("/%s/%s/%s/%s", bankName, collection, typeName, item));
285                itemAttributes.put("id",
286                        BankUtils.getDomId(String.format("%s-%s-%s-%s", bankName, collection, typeName, item)));
287                itemNode.put("attributes", itemAttributes);
288                itemNode.put("data", itemMap);
289
290                items.add(itemNode);
291            }
292            folderTypeNode.put("children", items);
293            folderTypeNodes.add(folderTypeNode);
294        }
295        collectionNode.put("children", folderTypeNodes);
296        return collectionNode;
297    }
298
299    /*
300     * IO
301     */
302    public static StreamingOutput streamFile(final File file) {
303        return new StreamingOutput() {
304            @Override
305            public void write(OutputStream out) throws IOException, WebApplicationException {
306                InputStream in = null;
307                try {
308                    in = new FileInputStream(file);
309                    IOUtils.copy(in, out);
310                } catch (FileNotFoundException e) {
311                    throw new WebApplicationException(e, Response.Status.NOT_FOUND);
312                } catch (IOException e) {
313                    throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
314                } finally {
315                    IOUtils.closeQuietly(in);
316                }
317            }
318        };
319    }
320
321}