001/*
002 * (C) Copyright 2006-2014 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 *     Jean-Marc Orliaguet, Chalmers
018 *
019 */
020
021package org.nuxeo.theme.presets;
022
023import java.io.DataInputStream;
024import java.io.FileNotFoundException;
025import java.io.IOException;
026import java.io.InputStream;
027import java.io.StringReader;
028import java.io.StringWriter;
029import java.net.URL;
030import java.util.HashMap;
031import java.util.Map;
032
033import org.apache.commons.csv.CSVFormat;
034import org.apache.commons.csv.CSVParser;
035import org.apache.commons.csv.CSVPrinter;
036import org.apache.commons.csv.CSVRecord;
037import org.apache.commons.logging.Log;
038import org.apache.commons.logging.LogFactory;
039
040public class PaletteParser {
041
042    private static final Log log = LogFactory.getLog(PaletteParser.class);
043
044    public static Map<String, String> parse(URL url) {
045        Map<String, String> entries = new HashMap<>();
046        InputStream in = null;
047        try {
048            in = url.openStream();
049            entries = parse(in, url.getFile());
050        } catch (FileNotFoundException e) {
051            log.error("File not found: " + url);
052        } catch (IOException e) {
053            log.error("Could not open file: " + url);
054        } catch (PaletteIdentifyException e) {
055            log.error("Could not identify palette type: " + url);
056        } catch (PaletteParseException e) {
057            log.error("Could not parse palette: " + url);
058        } finally {
059            if (in != null) {
060                try {
061                    in.close();
062                } catch (IOException e) {
063                    log.error(e, e);
064                } finally {
065                    in = null;
066                }
067            }
068        }
069        return entries;
070    }
071
072    public static boolean checkSanity(byte[] bytes) {
073        return false;
074    }
075
076    public static String rgbToHex(int r, int g, int b) {
077        final StringBuffer hexcolor = new StringBuffer("#");
078        final int[] rgb = { r, g, b };
079        for (final int val : rgb) {
080            if (val < 16) {
081                hexcolor.append("0");
082            }
083            hexcolor.append(Integer.toHexString(val));
084        }
085        // optimize #aabbcc to #abc
086        if (hexcolor.charAt(1) == hexcolor.charAt(2) && hexcolor.charAt(3) == hexcolor.charAt(4)
087                && hexcolor.charAt(5) == hexcolor.charAt(6)) {
088            return String.format("#%s%s%s", hexcolor.charAt(1), hexcolor.charAt(4), hexcolor.charAt(6));
089        }
090        return hexcolor.toString();
091    }
092
093    public static PaletteFamily identifyPaletteType(byte[] bytes, String filename) throws PaletteIdentifyException {
094        if (filename.endsWith(".aco") && PhotoshopPaletteParser.checkSanity(bytes)) {
095            return PaletteFamily.PHOTOSHOP;
096        } else if (filename.endsWith(".gpl") && GimpPaletteParser.checkSanity(bytes)) {
097            return PaletteFamily.GIMP;
098        } else if (filename.endsWith(".properties") && PropertiesPaletteParser.checkSanity(bytes)) {
099            return PaletteFamily.PROPERTIES;
100        }
101        throw new PaletteIdentifyException();
102    }
103
104    public static Map<String, String> parse(InputStream in, String filename) throws IOException,
105            PaletteIdentifyException, PaletteParseException {
106        DataInputStream dis = new DataInputStream(in);
107        byte[] bytes = new byte[dis.available()];
108        dis.read(bytes);
109        return parse(bytes, filename);
110    }
111
112    public static Map<String, String> parse(byte[] bytes, String filename) throws PaletteIdentifyException,
113            PaletteParseException {
114        PaletteFamily paletteFamily = identifyPaletteType(bytes, filename);
115        if (paletteFamily == PaletteFamily.PHOTOSHOP) {
116            return PhotoshopPaletteParser.parse(bytes);
117        } else if (paletteFamily == PaletteFamily.GIMP) {
118            return GimpPaletteParser.parse(bytes);
119        } else if (paletteFamily == PaletteFamily.PROPERTIES) {
120            return PropertiesPaletteParser.parse(bytes);
121        }
122        if (paletteFamily == null) {
123            throw new PaletteParseException();
124        }
125        return null;
126    }
127
128    public static String renderPaletteAsCsv(byte[] bytes, String fileName) {
129        StringWriter sw = new StringWriter();
130        try (CSVPrinter writer = new CSVPrinter(sw, CSVFormat.DEFAULT.withDelimiter('\t'))) {
131            for (Map.Entry<String, String> entry : parse(bytes, fileName).entrySet()) {
132                writer.printRecord(entry.getKey(), entry.getValue());
133            }
134        } catch (PaletteIdentifyException e) {
135            log.warn("Could not identify palette type: " + fileName);
136        } catch (PaletteParseException e) {
137            log.warn("Could not parse palette: " + fileName);
138        } catch (IOException e) {
139            log.error(e.getMessage(), e);
140        }
141        return sw.toString();
142    }
143
144    public static Map<String, String> parseCsv(String text) {
145        Map<String, String> properties = new HashMap<>();
146        if (text == null) {
147            return properties;
148        }
149        try (StringReader sr = new StringReader(text);
150                CSVParser reader = new CSVParser(sr, CSVFormat.DEFAULT.withDelimiter('\t'))) {
151            for (CSVRecord record : reader) {
152                properties.put(record.get(0), record.get(1));
153            }
154        } catch (IOException e) {
155            log.error(e, e);
156        }
157        return properties;
158    }
159
160}