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