001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.util.ArrayUtil;
018    import com.liferay.portal.kernel.xml.simple.Element;
019    import com.liferay.util.xml.XMLFormatter;
020    
021    import java.io.IOException;
022    import java.io.Serializable;
023    
024    import java.util.Collections;
025    import java.util.Enumeration;
026    import java.util.HashMap;
027    import java.util.Map;
028    import java.util.concurrent.ConcurrentHashMap;
029    
030    import javax.portlet.ReadOnlyException;
031    import javax.portlet.ValidatorException;
032    
033    /**
034     * @author Alexander Chow
035     * @author Shuyang Zhou
036     */
037    public abstract class BasePreferencesImpl implements Serializable {
038    
039            public BasePreferencesImpl(
040                    long ownerId, int ownerType, String xml,
041                    Map<String, Preference> preferences) {
042    
043                    _ownerId = ownerId;
044                    _ownerType = ownerType;
045                    _originalXML = xml;
046                    _originalPreferences = preferences;
047            }
048    
049            public Map<String, String[]> getMap() {
050                    Map<String, String[]> map = new HashMap<String, String[]>();
051    
052                    Map<String, Preference> preferences = getPreferences();
053    
054                    for (Map.Entry<String, Preference> entry : preferences.entrySet()) {
055                            String key = entry.getKey();
056                            Preference preference = entry.getValue();
057    
058                            String[] actualValues = getActualValues(preference.getValues());
059    
060                            map.put(key, actualValues);
061                    }
062    
063                    return Collections.unmodifiableMap(map);
064            }
065    
066            public Enumeration<String> getNames() {
067                    Map<String, Preference> preferences = getPreferences();
068    
069                    return Collections.enumeration(preferences.keySet());
070            }
071    
072            public long getOwnerId() {
073                    return _ownerId;
074            }
075    
076            public int getOwnerType() {
077                    return _ownerType;
078            }
079    
080            public String getValue(String key, String def) {
081                    if (key == null) {
082                            throw new IllegalArgumentException();
083                    }
084    
085                    Map<String, Preference> preferences = getPreferences();
086    
087                    Preference preference = preferences.get(key);
088    
089                    String[] values = null;
090    
091                    if (preference != null) {
092                            values = preference.getValues();
093                    }
094    
095                    if (!isNull(values)) {
096                            return getActualValue(values[0]);
097                    }
098                    else {
099                            return getActualValue(def);
100                    }
101            }
102    
103            public String[] getValues(String key, String[] def) {
104                    if (key == null) {
105                            throw new IllegalArgumentException();
106                    }
107    
108                    Map<String, Preference> preferences = getPreferences();
109    
110                    Preference preference = preferences.get(key);
111    
112                    String[] values = null;
113    
114                    if (preference != null) {
115                            values = preference.getValues();
116                    }
117    
118                    if (!isNull(values)) {
119                            return getActualValues(values);
120                    }
121                    else {
122                            return getActualValues(def);
123                    }
124            }
125    
126            public boolean isReadOnly(String key) {
127                    if (key == null) {
128                            throw new IllegalArgumentException();
129                    }
130    
131                    Map<String, Preference> preferences = getPreferences();
132    
133                    Preference preference = preferences.get(key);
134    
135                    if ((preference != null) && preference.isReadOnly()) {
136                            return true;
137                    }
138                    else {
139                            return false;
140                    }
141            }
142    
143            public void reset() {
144                    _modifiedPreferences = null;
145            }
146    
147            public abstract void reset(String key) throws ReadOnlyException;
148    
149            public void setValue(String key, String value) throws ReadOnlyException {
150                    if (key == null) {
151                            throw new IllegalArgumentException();
152                    }
153    
154                    value = getXMLSafeValue(value);
155    
156                    Map<String, Preference> modifiedPreferences = getModifiedPreferences();
157    
158                    Preference preference = modifiedPreferences.get(key);
159    
160                    if (preference == null) {
161                            preference = new Preference(key, value);
162    
163                            modifiedPreferences.put(key, preference);
164                    }
165    
166                    if (preference.isReadOnly()) {
167                            throw new ReadOnlyException(key);
168                    }
169                    else {
170                            preference = (Preference)preference.clone();
171    
172                            modifiedPreferences.put(key, preference);
173    
174                            preference.setValues(new String[] {value});
175                    }
176            }
177    
178            public void setValues(String key, String[] values)
179                    throws ReadOnlyException {
180    
181                    if (key == null) {
182                            throw new IllegalArgumentException();
183                    }
184    
185                    values = getXMLSafeValues(values);
186    
187                    Map<String, Preference> modifiedPreferences = getModifiedPreferences();
188    
189                    Preference preference = modifiedPreferences.get(key);
190    
191                    if (preference == null) {
192                            preference = new Preference(key, values);
193    
194                            modifiedPreferences.put(key, preference);
195                    }
196    
197                    if (preference.isReadOnly()) {
198                            throw new ReadOnlyException(key);
199                    }
200                    else {
201                            preference = (Preference)preference.clone();
202    
203                            modifiedPreferences.put(key, preference);
204    
205                            preference.setValues(values);
206                    }
207            }
208    
209            public int size() {
210                    Map<String, Preference> preferences = getPreferences();
211    
212                    return preferences.size();
213            }
214    
215            public abstract void store() throws IOException, ValidatorException;
216    
217            protected String getActualValue(String value) {
218                    if ((value == null) || value.equals(_NULL_VALUE)) {
219                            return null;
220                    }
221                    else {
222                            return XMLFormatter.fromCompactSafe(value);
223                    }
224            }
225    
226            protected String[] getActualValues(String[] values) {
227                    if (values == null) {
228                            return null;
229                    }
230    
231                    if (values.length == 1) {
232                            String actualValue = getActualValue(values[0]);
233    
234                            if (actualValue == null) {
235                                    return null;
236                            }
237                            else {
238                                    return new String[] {actualValue};
239                            }
240                    }
241    
242                    String[] actualValues = new String[values.length];
243    
244                    for (int i = 0; i < actualValues.length; i++) {
245                            actualValues[i] = getActualValue(values[i]);
246                    }
247    
248                    return actualValues;
249            }
250    
251            protected Map<String, Preference> getModifiedPreferences() {
252                    if (_modifiedPreferences == null) {
253                            _modifiedPreferences = new ConcurrentHashMap<String, Preference>(
254                                    _originalPreferences);
255                    }
256    
257                    return _modifiedPreferences;
258            }
259    
260            protected Map<String, Preference> getOriginalPreferences() {
261                    return _originalPreferences;
262            }
263    
264            protected String getOriginalXML() {
265                    return _originalXML;
266            }
267    
268            protected Map<String, Preference> getPreferences() {
269                    if (_modifiedPreferences != null) {
270                            return _modifiedPreferences;
271                    }
272    
273                    return _originalPreferences;
274            }
275    
276            protected String getXMLSafeValue(String value) {
277                    if (value == null) {
278                            return _NULL_VALUE;
279                    }
280                    else {
281                            return XMLFormatter.toCompactSafe(value);
282                    }
283            }
284    
285            protected String[] getXMLSafeValues(String[] values) {
286                    if (values == null) {
287                            return new String[] {_NULL_VALUE};
288                    }
289    
290                    String[] xmlSafeValues = new String[values.length];
291    
292                    for (int i = 0; i < xmlSafeValues.length; i++) {
293                            xmlSafeValues[i] = getXMLSafeValue(values[i]);
294                    }
295    
296                    return xmlSafeValues;
297            }
298    
299            protected boolean isNull(String[] values) {
300                    if (ArrayUtil.isEmpty(values) ||
301                            ((values.length == 1) && (getActualValue(values[0]) == null))) {
302    
303                            return true;
304                    }
305    
306                    return false;
307            }
308    
309            protected void setOriginalPreferences(
310                    Map<String, Preference> originalPreferences) {
311    
312                    _originalPreferences = originalPreferences;
313            }
314    
315            protected void setOriginalXML(String originalXML) {
316                    _originalXML = originalXML;
317            }
318    
319            protected String toXML() {
320                    if ((_modifiedPreferences == null) && (_originalXML != null)) {
321                            return _originalXML;
322                    }
323    
324                    Map<String, Preference> preferences = getPreferences();
325    
326                    Element portletPreferencesElement = new Element(
327                            "portlet-preferences", false);
328    
329                    for (Map.Entry<String, Preference> entry : preferences.entrySet()) {
330                            Preference preference = entry.getValue();
331    
332                            Element preferenceElement = portletPreferencesElement.addElement(
333                                    "preference");
334    
335                            preferenceElement.addElement("name", preference.getName());
336    
337                            for (String value : preference.getValues()) {
338                                    preferenceElement.addElement("value", value);
339                            }
340    
341                            if (preference.isReadOnly()) {
342                                    preferenceElement.addElement("read-only", Boolean.TRUE);
343                            }
344                    }
345    
346                    return portletPreferencesElement.toXMLString();
347            }
348    
349            private static final String _NULL_VALUE = "NULL_VALUE";
350    
351            private Map<String, Preference> _modifiedPreferences;
352            private Map<String, Preference> _originalPreferences;
353            private String _originalXML;
354            private long _ownerId;
355            private int _ownerType;
356    
357    }