/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.toolkit.util.resourcebundle.xml;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import com.alibaba.toolkit.util.ContextClassLoader;
import com.alibaba.toolkit.util.collection.ArrayHashMap;
import com.alibaba.toolkit.util.collection.ListMap;
import com.alibaba.toolkit.util.enumeration.Enum;
import com.alibaba.toolkit.util.resourcebundle.ResourceBundle;
import com.alibaba.toolkit.util.resourcebundle.ResourceBundleConstant;
import com.alibaba.toolkit.util.resourcebundle.ResourceBundleCreateException;
import com.alibaba.toolkit.util.resourcebundle.ResourceBundleEnumeration;
import org.dom4j.Document;
import org.dom4j.Node;
/**
* XML格式的<code>ResourceBundle</code>.
*
* @author Michael Zhou
* @version $Id: XMLResourceBundle.java,v 1.1 2003/07/03 07:26:35 baobao Exp $
*/
public class XMLResourceBundle extends ResourceBundle {
protected ListMap values = new ArrayHashMap();
/**
* 从XML文档中创建<code>ResourceBundle</code>.
*
* @param doc XML文档
* @throws ResourceBundleCreateException 解析错误
*/
public XMLResourceBundle(Document doc) throws ResourceBundleCreateException {
// 解析group.
for (Iterator i = doc.selectNodes(ResourceBundleConstant.XPATH_GROUPS).iterator(); i.hasNext(); ) {
Node groupNode = (Node) i.next();
initGroup(groupNode);
}
// 解析没有group的resource.
for (Iterator i = doc.selectNodes(ResourceBundleConstant.XPATH_UNGROUPED_RESOURCES).iterator(); i.hasNext(); ) {
Node resourceNode = (Node) i.next();
initResource(resourceNode, null);
}
}
/**
* 根据XML Node初始化一个resource项.
*
* @param groupNode 代表resource信息的XML Node
* @throws ResourceBundleCreateException 解析错误
*/
protected void initGroup(Node groupNode) throws ResourceBundleCreateException {
String enumTypeName = (String) groupNode.selectObject(ResourceBundleConstant.XPATH_GROUP_ENUM);
Class enumType = null;
if (enumTypeName.length() > 0) {
try {
enumType = ContextClassLoader.loadClass(enumTypeName);
} catch (ClassNotFoundException e) {
throw new ResourceBundleCreateException(ResourceBundleConstant.RB_ENUM_CLASS_NOT_FOUND, new Object[] {
enumTypeName, ContextClassLoader.getClassLoader() }, e);
}
}
for (Iterator i = groupNode.selectNodes(ResourceBundleConstant.XPATH_RESOURCES).iterator(); i.hasNext(); ) {
Node resourceNode = (Node) i.next();
initResource(resourceNode, enumType);
}
}
/**
* 根据XML Node初始化一个resource项.
*
* @param resourceNode 代表resource信息的XML Node
* @param enumType <code>Enum</code>类
* @throws ResourceBundleCreateException 解析错误
*/
protected void initResource(Node resourceNode, Class enumType) throws ResourceBundleCreateException {
String id = (String) resourceNode.selectObject(ResourceBundleConstant.XPATH_RESOURCE_ID);
// 如果指定了enum属性, 则以此enum值作为resource key.
if (enumType != null) {
Enum enumObj = Enum.getEnumByName(enumType, id);
if (enumObj == null) {
throw new ResourceBundleCreateException(ResourceBundleConstant.RB_ENUM_ID_NOT_FOUND, new Object[] { id,
enumType.getName() }, null);
}
id = enumObj.toString();
}
Object value = null;
String type = resourceNode.getName();
if (ResourceBundleConstant.RB_RESOURCE_TYPE_MESSAGE.equals(type)) {
value = getMessageResource(id, resourceNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_MAP.equals(type)) {
value = getMapResource(id, resourceNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_LIST.equals(type)) {
value = getListResource(id, resourceNode);
}
if (values.containsKey(id)) {
throw new ResourceBundleCreateException(ResourceBundleConstant.RB_DUPLICATED_RESOURCE_KEY,
new Object[] { id }, null);
}
values.put(id, value);
}
/**
* 根据XML Node创建message resource项.
*
* @param id resource ID
* @param resourceNode 代表resource信息的XML Node
* @return resource的值
* @throws ResourceBundleCreateException 解析错误
*/
protected Object getMessageResource(String id, Node resourceNode) throws ResourceBundleCreateException {
return resourceNode.selectObject(ResourceBundleConstant.XPATH_RESOURCE_MESSAGE_DATA);
}
/**
* 根据XML Node创建map resource项.
*
* @param id resource ID
* @param resourceNode 代表resource信息的XML Node
* @return resource的值
* @throws ResourceBundleCreateException 解析错误
*/
protected Object getMapResource(String id, Node resourceNode) throws ResourceBundleCreateException {
ListMap map = new ArrayHashMap();
for (Iterator i = resourceNode.selectNodes(ResourceBundleConstant.XPATH_RESOURCES).iterator(); i.hasNext(); ) {
Node mapItemNode = (Node) i.next();
Object mapKey = mapItemNode.selectObject(ResourceBundleConstant.XPATH_RESOURCE_ID);
if (map.containsKey(id)) {
throw new ResourceBundleCreateException(ResourceBundleConstant.RB_DUPLICATED_MAP_RESOURCE_KEY,
new Object[] { mapKey, id }, null);
}
String mapItemType = mapItemNode.getName();
Object value = null;
if (ResourceBundleConstant.RB_RESOURCE_TYPE_MESSAGE.equals(mapItemType)) {
value = getMessageResource(id, mapItemNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_MAP.equals(mapItemType)) {
value = getMapResource(id, mapItemNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_LIST.equals(mapItemType)) {
value = getListResource(id, mapItemNode);
}
map.put(mapKey, value);
}
return Collections.unmodifiableMap(map);
}
/**
* 根据XML Node创建list resource项.
*
* @param id resource ID
* @param resourceNode 代表resource信息的XML Node
* @return resource的值
* @throws ResourceBundleCreateException 解析错误
*/
protected Object getListResource(String id, Node resourceNode) throws ResourceBundleCreateException {
List list = new ArrayList();
for (Iterator i = resourceNode.selectNodes(ResourceBundleConstant.XPATH_RESOURCES).iterator(); i.hasNext(); ) {
Node listItemNode = (Node) i.next();
String listItemType = listItemNode.getName();
Object value = null;
if (ResourceBundleConstant.RB_RESOURCE_TYPE_MESSAGE.equals(listItemType)) {
value = getMessageResource(id, listItemNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_MAP.equals(listItemType)) {
value = getMapResource(id, listItemNode);
} else if (ResourceBundleConstant.RB_RESOURCE_TYPE_LIST.equals(listItemType)) {
value = getListResource(id, listItemNode);
}
list.add(value);
}
return Collections.unmodifiableList(list);
}
/**
* 根据指定的键, 从resource bundle中取得相应的对象. 如果返回<code>null</code>表示对应的对象不存在.
*
* @param key 要查找的键
* @return key对应的对象, 或<code>null</code>表示不存在该对象
*/
@Override
protected Object handleGetObject(String key) {
return values.get(key);
}
/**
* 取得所有keys.
*
* @return 所有keys
*/
@Override
public Enumeration getKeys() {
java.util.ResourceBundle parent = getParent();
return new ResourceBundleEnumeration(values.keySet(), parent != null ? parent.getKeys() : null);
}
}