/* * Copyright 2008-2010 the T2 Project ant the Others. * * 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.t2framework.confeito.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.t2framework.confeito.contexts.Request; import org.t2framework.confeito.util.Assertion; import org.t2framework.confeito.util.PatternUtil; import org.t2framework.confeito.util.StringUtil; /** * * <#if locale="en"> * <p> * Request parsing and converting utility for request like hoge[0][1]. * </p> * <#else> * <p> * * </p> * </#if> * * TODO convert as array. * * @author shot * */ public class RequestParseUtil { public static final String REGEX = "([^\\]]+)(?:\\[(\\d+)\\])?(?:\\[(\\d+)\\])?"; public static final int MAX = 1000; public static Map<String, Map<Integer, Object>> createParamMap( Request request) { Map<String, Map<Integer, Object>> map = new HashMap<String, Map<Integer, Object>>(); for (String key : request.getParameterNames()) { String value = request.getParameter(key); parse(key, value, map); } return map; } protected static Map<Integer, Object> createMap() { return new TreeMap<Integer, Object>(); } @SuppressWarnings("unchecked") public static void parse(String key, String value, Map<String, Map<Integer, Object>> context) { Assertion.notNull(key); Assertion.notNull(value); int head = key.indexOf("["); int tail = key.indexOf("]"); // fast check if (0 < head && head < tail) { final Pattern pattern = PatternUtil.getPattern(REGEX); Matcher matcher = pattern.matcher(key); if (matcher.matches() == false) { throw new IllegalStateException("unmatch"); } int groupCount = matcher.groupCount(); String propertyName = matcher.group(1); Map<Integer, Object> root = null; if (context.containsKey(propertyName)) { root = context.get(propertyName); } else { root = createMap(); context.put(propertyName, root); } Map<Integer, Object> map = root; for (int i = 2; i < groupCount + 1; i++) { String s = matcher.group(i); if (StringUtil.isEmpty(s)) { break; } Integer mapKey = Integer.valueOf(s); if (MAX < mapKey.intValue()) { throw new IllegalStateException( "Can not keep more than 1000 entry."); } boolean nextNull = (i == groupCount) ? true : StringUtil .isEmpty(matcher.group(i + 1)); if (nextNull) { if (map.containsKey(mapKey)) { throw new IllegalStateException("dimension error."); } else { map.put(mapKey, value); } } else { Map<Integer, Object> m = null; if (map.containsKey(mapKey)) { Object o = map.get(mapKey); if (o instanceof Map) { m = (Map<Integer, Object>) o; } } else { m = createMap(); } if (m != null) { map.put(mapKey, m); map = m; } } } } } public static List<Object> convertAsList(Map<Integer, Object> map) { List<Object> ret = new ArrayList<Object>(); walk(ret, map); return ret; } @SuppressWarnings("unchecked") protected static void walk(List<Object> root, Map<Integer, Object> map) { for (Entry<Integer, Object> entry : map.entrySet()) { Object value = entry.getValue(); if (value instanceof Map) { Map<Integer, Object> m = (Map<Integer, Object>) value; List<Object> list = new ArrayList<Object>(); root.add(list); walk(list, m); } else { root.add(value); } } } }