/* * Copyright 2012 James Moger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.moxie.maxml; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.regex.Pattern; import org.moxie.utils.StringUtils; /** * MaxmlMap is a subclass of LinkedHashMap that forces keys to lowercase. */ public class MaxmlMap extends LinkedHashMap<String, Object> { private static final long serialVersionUID = 1L; @Override public boolean containsKey(Object key) { return super.containsKey(key.toString().toLowerCase()); } @Override public Object get(Object key) { return super.get(key.toString().toLowerCase()); } @Override public Object put(String key, Object value) { return super.put(key.toString().toLowerCase(), value); } @Override public Object remove(Object key) { return super.remove(key.toString().toLowerCase()); } public boolean getBoolean(String key, boolean defaultValue) { if (containsKey(key)) { Object o = get(key); if (o instanceof Boolean) { return (Boolean) o; } return Boolean.parseBoolean(o.toString()); } return defaultValue; } public int getInt(String key, int defaultValue) { if (containsKey(key)) { Object o = get(key); if (o instanceof Number) { return ((Number) o).intValue(); } return Integer.parseInt(o.toString()); } return defaultValue; } public String getString(String key, String defaultValue) { if (containsKey(key)) { Object o = get(key); return o.toString(); } return defaultValue; } @SuppressWarnings("unchecked") public List<String> getStrings(String key, List<String> defaultValue) { if (containsKey(key)) { Object o = get(key); if (o instanceof List<?>) { return (List<String>) o; } else if (o instanceof String) { List<String> strings = new ArrayList<String>(); for (String value : o.toString().split(",")) { strings.add(StringUtils.stripQuotes(value.trim())); } return strings; } } return defaultValue; } public Date getDate(String key, Date defaultValue) { if (containsKey(key)) { Object o = get(key); if (o instanceof Date) { return (Date) o; } else if (o instanceof String) { // try to convert the string to a date DateFormat canonical = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); DateFormat date = new SimpleDateFormat("yyyy-MM-dd"); Pattern datePattern = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}"); if (datePattern.matcher((String) o).find()) { DateFormat[] formats = { canonical, iso8601, date }; for (DateFormat df : formats) { try { Date aDate = df.parse((String) o); // reset milliseconds to 0 Calendar cal = Calendar.getInstance(); cal.setTime(aDate); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } catch (Throwable t) { // t.printStackTrace(); } } } } } return defaultValue; } public List<?> getList(String key, List<?> defaultValue) { if (containsKey(key)) { Object o = get(key); if (o instanceof List<?>) { return (List<?>) o; } else if (o instanceof String) { return Arrays.asList(o.toString()); } } return defaultValue; } public MaxmlMap getMap(String key) { if (containsKey(key)) { Object o = get(key); if (o instanceof MaxmlMap) { return (MaxmlMap) o; } } return null; } public String toMaxml() { StringBuilder sb = new StringBuilder(); for (String key : keySet()) { Object o = get(key); if (o instanceof MaxmlMap) { sb.append(escapeKey(key)).append(": {\n"); sb.append(((MaxmlMap) o).toMaxml()); sb.append("\n}\n"); } else if (o instanceof List) { sb.append(escapeKey(key)).append(":\n"); for (Object j : ((List<?>) o)) { sb.append("- ").append(toMaxml(j)).append('\n'); } } else { sb.append(escapeKey(key)).append(": ").append(toMaxml(o)).append('\n'); } } return sb.toString(); } String escapeKey(String key) { if (key.indexOf(':') > -1) { return "\"" + key + "\""; } return key; } String toMaxml(Object o) { StringBuilder sb = new StringBuilder(); if (o instanceof MaxmlMap) { // inline-map sb.append(" { "); MaxmlMap map = (MaxmlMap) o; for (String key : map.keySet()) { sb.append(escapeKey(key)).append(':').append(toMaxml(map.get(key))).append(", "); sb.append(((MaxmlMap) o).toMaxml()); } // trim trailing comma-space sb.setLength(sb.length() - 2); sb.append(" }"); } else if (o instanceof List) { // in-line list sb.append(" [ "); for (Object j : ((List<?>) o)) { sb.append("\"").append(toMaxml(j)).append("\", "); } // trim trailing comma-space sb.setLength(sb.length() - 2); sb.append(" ]"); } else if (o instanceof java.sql.Date) { // date DateFormat date = new SimpleDateFormat("yyyy-MM-dd"); sb.append(date.format((Date) o)).append('\n'); } else if (o instanceof Date) { // full date DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); sb.append(iso8601.format((Date) o)).append('\n'); } else { // number, boolean, string sb.append(o); } return sb.toString(); } }