001    /**
002     * Copyright (c) 2000-2012 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.portal.json;
016    
017    import com.liferay.portal.kernel.json.JSON;
018    import com.liferay.portal.kernel.util.StringPool;
019    
020    import java.lang.reflect.Field;
021    import java.lang.reflect.Method;
022    
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.List;
026    import java.util.Map;
027    
028    /**
029     * @author Igor Spasic
030     */
031    public class JSONIncludesManager {
032    
033            public String[] lookupExcludes(Class<?> type) {
034                    String[] excludes = _excludesMap.get(type);
035    
036                    if (excludes != null) {
037                            return excludes;
038                    }
039    
040                    List<String> list = new ArrayList<String>();
041    
042                    while (type != null) {
043                            JSON jsonAnnotation = type.getAnnotation(JSON.class);
044    
045                            if ((jsonAnnotation != null) && jsonAnnotation.strict()) {
046                                    list.add(_EXCLUDE_ALL);
047    
048                                    break;
049                            }
050                            else {
051                                    _scanFieldsAndMethods(list, type, false);
052                            }
053    
054                            type = type.getSuperclass();
055                    }
056    
057                    excludes = _listToArray(list);
058    
059                    _excludesMap.put(type, excludes);
060    
061                    return excludes;
062            }
063    
064            public String[] lookupIncludes(Class<?> type) {
065                    String[] includes = _includesMap.get(type);
066    
067                    if (includes != null) {
068                            return includes;
069                    }
070    
071                    List<String> list = new ArrayList<String>();
072    
073                    while (type != null) {
074                            _scanFieldsAndMethods(list, type, true);
075    
076                            type = type.getSuperclass();
077                    }
078    
079                    includes = _listToArray(list);
080    
081                    _includesMap.put(type, includes);
082    
083                    return includes;
084            }
085    
086            private String _getPropertyName(Method method) {
087                    Class<?>[] parameterTypes = method.getParameterTypes();
088    
089                    if (parameterTypes.length != 0) {
090                            return null;
091                    }
092    
093                    String propertyName = null;
094    
095                    String methodName = method.getName();
096    
097                    if (methodName.startsWith("get")) {
098                            propertyName = methodName.substring(3);
099                    }
100                    else if (methodName.startsWith("is")) {
101                            propertyName = methodName.substring(2);
102                    }
103                    else {
104                            return null;
105                    }
106    
107                    if ((propertyName.length() > 2) &&
108                            Character.isUpperCase(propertyName.charAt(1))) {
109    
110                            return propertyName;
111                    }
112    
113                    return Character.toLowerCase(propertyName.charAt(0)) +
114                            propertyName.substring(1);
115            }
116    
117            private String[] _listToArray(List<String> list) {
118                    if (list.isEmpty()) {
119                            return _EMPTY_LIST;
120                    }
121                    else {
122                            return list.toArray(new String[list.size()]);
123                    }
124            }
125    
126            private void _scanFieldsAndMethods(
127                    List<String> list, Class<?> type, boolean include) {
128    
129                    Field[] fields = type.getDeclaredFields();
130    
131                    for (Field field : fields) {
132                            JSON jsonAnnotation = field.getAnnotation(JSON.class);
133    
134                            if ((jsonAnnotation != null) &&
135                                    (jsonAnnotation.include() == include)) {
136    
137                                    String name = field.getName();
138    
139                                    if (name.startsWith(StringPool.UNDERLINE)) {
140                                            name = name.substring(1);
141                                    }
142    
143                                    if (!list.contains(name)) {
144                                            list.add(name);
145                                    }
146                            }
147                    }
148    
149                    Method[] methods = type.getDeclaredMethods();
150    
151                    for (Method method : methods) {
152                            JSON jsonAnnotation = method.getAnnotation(JSON.class);
153    
154                            if ((jsonAnnotation != null) &&
155                                    (jsonAnnotation.include() == include)) {
156    
157                                    String name = _getPropertyName(method);
158    
159                                    if (name != null) {
160                                            if (!list.contains(name)) {
161                                                    list.add(name);
162                                            }
163                                    }
164                            }
165                    }
166            }
167    
168            private static final String[] _EMPTY_LIST = new String[0];
169    
170            private static final String _EXCLUDE_ALL = "*";
171    
172            private Map<Class<?>, String[]> _excludesMap =
173                    new HashMap<Class<?>, String[]>();
174            private Map<Class<?>, String[]> _includesMap =
175                    new HashMap<Class<?>, String[]>();
176    
177    }