/*
* Copyright 2013 The Skfiy Open Association.
*
* 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.skfiy.typhon.spi;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.FilenameFilter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Singleton;
import javax.management.ObjectName;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.modeler.ManagedBean;
import org.skfiy.typhon.AbstractComponent;
import org.skfiy.typhon.ComponentException;
import org.skfiy.typhon.Constants;
import org.skfiy.typhon.dobj.ItemDobj;
import org.skfiy.typhon.script.ScriptManager;
import org.skfiy.typhon.spi.item.ItemCompleter;
import org.skfiy.typhon.spi.item.NotFoundItemException;
import org.skfiy.typhon.util.ComponentUtils;
import org.skfiy.typhon.util.MBeanUtils;
import org.skfiy.util.AntPathMatcher;
import org.skfiy.util.Assert;
import org.skfiy.util.PathMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Kevin Zou <kevinz@skfiy.org>
*/
@Singleton
public class ItemProvider extends AbstractComponent {
private static final Logger LOG = LoggerFactory.getLogger(ItemProvider.class);
private ObjectName oname;
private Map<String, ItemDobj> items = new HashMap<>();
@Resource
private Set<ItemCompleter> itemCompleters;
@Resource
private ScriptManager scriptManager;
/**
*
* @param <T>
* @param id
* @return
*/
public <T extends ItemDobj> T getItem(String id) {
Assert.notNull(id,
"[Assertion failed] - item \"id\" argument is required; it must not be null");
T item = (T) items.get(id);
if (item == null) {
throw new NotFoundItemException("Not found item [" + id + "]");
}
return item;
}
@Override
public void doInit() {
items.putAll(loadItems());
ManagedBean managedBean = MBeanUtils.findManagedBean(getClass());
MBeanUtils.registerComponent(this, managedBean);
LOG.info("item init successful.");
}
@Override
public void doReload() {
Map<String, ItemDobj> itemMap = loadItems();
for (Map.Entry<String, ItemDobj> entry : itemMap.entrySet()) {
ItemDobj oldItem = items.get(entry.getKey());
if (oldItem == null) {
items.put(entry.getKey(), entry.getValue());
} else {
try {
BeanUtils.copyProperties(oldItem, entry.getValue());
} catch (Exception ex) {
LOG.error("resetting item[id={}] failed.", entry.getKey(), ex);
throw new ComponentException(ex);
}
}
}
LOG.info("item reload successful.");
}
@Override
public void doDestroy() {
items.clear();
items = null;
if (oname != null) {
MBeanUtils.REGISTRY.unregisterComponent(oname);
}
LOG.info("item destroy successful.");
}
private Map<String, ItemDobj> loadItems() {
File[] itemFiles = findItemFiles();
JSONArray jsonArray = new JSONArray();
for (File file : itemFiles) {
jsonArray.addAll(JSON.parseArray(ComponentUtils.readDataFile(file)));
}
Map<String, ItemDobj> itemMap = new HashMap<>();
for (Iterator<Object> it = jsonArray.iterator(); it.hasNext();) {
JSONObject json = (JSONObject) it.next();
ItemCompleter itemCompleter = findItemCompleter(json.getString("type"));
try {
ItemDobj staticItem = itemCompleter.prepare(json);
if (json.containsKey("script")) {
staticItem.setScript(scriptManager.getScript(json.getString("script")));
}
itemMap.put(staticItem.getId(), staticItem);
} catch (Exception e) {
LOG.error("item {}", json.toJSONString(), e);
throw new ComponentException(e);
}
}
for (Iterator<Object> it = jsonArray.iterator(); it.hasNext();) {
JSONObject json = (JSONObject) it.next();
ItemCompleter itemCompleter = findItemCompleter(json.getString("type"));
try {
itemCompleter.complete(itemMap, json);
} catch (Exception e) {
LOG.error("item {}", json, e);
throw new ComponentException(e);
}
}
return itemMap;
}
private File[] findItemFiles() {
final PathMatcher pathMatcher = new AntPathMatcher();
File datasDir = new File(System.getProperty(Constants.COMPONENT_DATAS_DIR));
return datasDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return (!"item_monster.json".equals(name)
&& pathMatcher.match("item_*.json", name));
}
});
}
private ItemCompleter findItemCompleter(String type) {
for (ItemCompleter itemCompleter : itemCompleters) {
if (itemCompleter.getType().equals(type)) {
return itemCompleter;
}
}
throw new IllegalArgumentException("Not found ["
+ type + "] ItemCompleter");
}
}