001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Jean-Marc Orliaguet, Chalmers
011 *
012 * $Id$
013 */
014
015package org.nuxeo.theme.presets;
016
017import java.util.ArrayList;
018import java.util.List;
019import java.util.Map;
020import java.util.regex.Matcher;
021import java.util.regex.Pattern;
022
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025import org.nuxeo.theme.Manager;
026import org.nuxeo.theme.elements.ThemeElement;
027import org.nuxeo.theme.formats.styles.Style;
028import org.nuxeo.theme.themes.ThemeException;
029import org.nuxeo.theme.themes.ThemeManager;
030import org.nuxeo.theme.types.Type;
031import org.nuxeo.theme.types.TypeFamily;
032
033public class PresetManager {
034
035    static final Log log = LogFactory.getLog(PresetManager.class);
036
037    private static final Pattern manyPresetNamePattern = Pattern.compile(".*?\"(.*?)\".*?");
038
039    private static final Pattern presetNamePattern = Pattern.compile("^\"(.*?)\"$");
040
041    private static final Pattern globalPresetNamePattern = Pattern.compile("^\".*?\\((.*?)\\)\"$");
042
043    private static final Pattern customPresetNamePattern = Pattern.compile("^\"(.*?)\"$");
044
045    public static String extractPresetName(final String themeName, final String str) {
046        String s = str.trim();
047        final Matcher globalPresetNameMatcher = globalPresetNamePattern.matcher(s);
048        if (globalPresetNameMatcher.find()) {
049            Matcher presetMatcher = presetNamePattern.matcher(s);
050            if (presetMatcher.find()) {
051                return presetMatcher.group(1);
052            }
053        } else if (themeName != null) {
054            final Matcher customPresetNameMatcher = customPresetNamePattern.matcher(s);
055            if (customPresetNameMatcher.find()) {
056                return String.format("%s/%s", themeName, customPresetNameMatcher.group(1));
057            }
058        }
059        return null;
060    }
061
062    public static PresetType getPresetByName(final String name) {
063        return (PresetType) Manager.getTypeRegistry().lookup(TypeFamily.PRESET, name);
064    }
065
066    public static List<Type> getAllPresets() {
067        return Manager.getTypeRegistry().getTypes(TypeFamily.PRESET);
068    }
069
070    public static List<PresetType> getGlobalPresets(final String group, final String category) {
071        List<PresetType> presets = new ArrayList<PresetType>();
072        for (Type type : getAllPresets()) {
073            PresetType preset = (PresetType) type;
074            if (category != null && !(category.equals(preset.getCategory()))) {
075                continue;
076            }
077            if (group != null && !preset.getGroup().equals(group)) {
078                continue;
079            }
080            if (preset instanceof CustomPresetType) {
081                continue;
082            }
083            presets.add(preset);
084        }
085        return presets;
086    }
087
088    public static PresetType getCustomPreset(final String themeName, final String presetName) {
089        return getPresetByName(String.format("%s/%s", themeName, presetName));
090    }
091
092    public static List<PresetType> getCustomPresets(final String themeName) {
093        return getCustomPresets(themeName, null);
094    }
095
096    public static List<PresetType> getCustomPresets(final String themeName, final String category) {
097        List<PresetType> presets = new ArrayList<PresetType>();
098        for (Type type : getAllPresets()) {
099            PresetType preset = (PresetType) type;
100            if (!(preset instanceof CustomPresetType)) {
101                continue;
102            }
103            if (category != null && !preset.getCategory().equals(category)) {
104                continue;
105            }
106            if (themeName != null && !preset.getGroup().equals(themeName)) {
107                continue;
108            }
109            presets.add(preset);
110        }
111        return presets;
112    }
113
114    public static String resolvePresets(final String themeName, String propertyValue) {
115        // first-pass
116        propertyValue = resolveVariables(themeName, propertyValue);
117        // second-pass
118        propertyValue = resolveVariables(themeName, propertyValue);
119        return propertyValue;
120    }
121
122    private static String resolveVariables(final String themeName, final String str) {
123        Matcher m = manyPresetNamePattern.matcher(str);
124        StringBuilder sb = new StringBuilder();
125        int end = 0;
126        while (m.find()) {
127            end = m.end(1) + 1;
128            sb.append(str.substring(m.start(), m.start(1) - 1));
129            String presetStr = String.format("\"%s\"", m.group(1));
130            String presetName = extractPresetName(themeName, presetStr);
131            if (presetName == null) {
132                sb.append(presetStr);
133                continue;
134            }
135            PresetType preset = getPresetByName(presetName);
136            if (preset == null) {
137                log.warn(String.format("Preset '%s' could not be resolved in theme '%s'", presetName, themeName));
138                sb.append(presetStr);
139                continue;
140            }
141            sb.append(preset.getValue());
142        }
143        sb.append(str.substring(end));
144        return sb.toString();
145    }
146
147    public static void createCustomPreset(String themeName, String presetName, String category, String value,
148            String label, String description) {
149        CustomPresetType preset = new CustomPresetType(presetName, value, themeName, category, label, description);
150        Manager.getTypeRegistry().register(preset);
151    }
152
153    public static void editPreset(String themeName, String presetName, String value) {
154        PresetType preset = getCustomPreset(themeName, presetName);
155        preset.setValue(value);
156    }
157
158    public static void setPresetCategory(String themeName, String presetName, String category) {
159        PresetType preset = getCustomPreset(themeName, presetName);
160        preset.setCategory(category);
161    }
162
163    public static void renamePreset(String themeName, String oldName, String newName) throws ThemeException {
164        if (newName.equals("")) {
165            throw new ThemeException("Preset name cannot be empty");
166        }
167        PresetType preset = getCustomPreset(themeName, oldName);
168        if (getCustomPreset(themeName, newName) != null) {
169            throw new ThemeException("Preset name already taken: " + newName);
170        }
171        Manager.getTypeRegistry().unregister(preset);
172        preset.setName(newName);
173        Manager.getTypeRegistry().register(preset);
174    }
175
176    public static void deletePreset(String themeName, String presetName) throws ThemeException {
177        PresetType preset = getCustomPreset(themeName, presetName);
178        if (getCustomPreset(themeName, presetName) == null) {
179            throw new ThemeException("Preset unknown: " + presetName);
180        }
181        Manager.getTypeRegistry().unregister(preset);
182    }
183
184    public static void clearCustomPresets(String themeName) {
185        for (PresetType preset : getCustomPresets(themeName)) {
186            Manager.getTypeRegistry().unregister(preset);
187        }
188    }
189
190    public static List<String> getUnidentifiedPresetNames(final String themeName) {
191        List<String> names = new ArrayList<String>();
192        ThemeManager themeManager = Manager.getThemeManager();
193        for (Style style : themeManager.getStyles()) {
194
195            if (style.isNamed()) {
196                if (!themeName.equals(themeManager.getThemeNameOfNamedObject(style))) {
197                    continue;
198                }
199            } else {
200                ThemeElement theme = ThemeManager.getThemeOfFormat(style);
201                if (theme == null) {
202                    continue;
203                }
204                if (!themeName.equals(theme.getName())) {
205                    continue;
206                }
207            }
208
209            for (Map.Entry<Object, Object> entry : style.getAllProperties().entrySet()) {
210                String value = (String) entry.getValue();
211                String s = value.trim();
212                Matcher m = manyPresetNamePattern.matcher(value.trim());
213                while (m.find()) {
214                    String name = m.group(1);
215                    String presetStr = String.format("\"%s\"", name);
216                    String presetName = extractPresetName(themeName, presetStr);
217                    if (presetName == null) {
218                        continue;
219                    }
220                    // retain only local theme presets
221                    if (globalPresetNamePattern.matcher(s).find()) {
222                        continue;
223                    }
224                    PresetType preset = getPresetByName(presetName);
225                    if (preset == null && !names.contains(name)) {
226                        names.add(name);
227                    }
228                }
229            }
230        }
231        return names;
232    }
233
234}