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