package com.brucezee.jspider.parser.spring.schema; import com.brucezee.jspider.parser.define.FieldDefine; import com.brucezee.jspider.parser.processor.FieldProcessor; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.lang.reflect.Constructor; import java.util.LinkedList; import java.util.List; /** * Created by zhoubing on 2016/12/8. */ public class FieldDefineBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext parserContext) { FieldDefine fieldDefine = parseFieldDefine(element); String id = fieldDefine.getId(); if (StringUtils.isEmpty(id)) { id = fieldDefine.toString()+"-"+System.currentTimeMillis(); } RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(FieldDefine.class); beanDefinition.setLazyInit(false); BeanDefinitionRegistry registry = parserContext.getRegistry(); if (registry.containsBeanDefinition(id)) { throw new IllegalStateException("Duplicate spring bean id " + id); } registry.registerBeanDefinition(id, beanDefinition); MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); propertyValues.addPropertyValue("id", id); propertyValues.addPropertyValue("name", fieldDefine.getName()); propertyValues.addPropertyValue("type", fieldDefine.getType()); propertyValues.addPropertyValue("selector", fieldDefine.getSelector()); propertyValues.addPropertyValue("processor", fieldDefine.getProcessor()); propertyValues.addPropertyValue("defines", fieldDefine.getDefines()); return beanDefinition; } private FieldDefine parseFieldDefine(Element defineElement) { String id = defineElement.getAttribute("id"); String type = defineElement.getAttribute("type"); String name = defineElement.getAttribute("name"); String selector = defineElement.getAttribute("selector"); FieldDefine fieldDefine = new FieldDefine(); fieldDefine.setId(id); fieldDefine.setType(type); fieldDefine.setName(name); fieldDefine.setSelector(selector); parseFieldDefines(fieldDefine, defineElement); return fieldDefine; } private void parseFieldDefines(FieldDefine fieldDefine, Element defineElement) { NodeList nodeList = defineElement.getChildNodes(); if (nodeList != null && nodeList.getLength() > 0) { int length = nodeList.getLength(); List<FieldDefine> list = new LinkedList<FieldDefine>(); for (int i = 0; i < length; i++) { Node node = nodeList.item(i); if (node instanceof Element) { Element element = (Element) node; if ("selector".equals(element.getLocalName())) { fieldDefine.setSelector(element.getTextContent()); } else if ("processor".equals(element.getLocalName())) { fieldDefine.setProcessor(getFieldProcessor(element)); } else { list.add(parseFieldDefine(element)); } } } if (list.size() > 0) { fieldDefine.setDefines(list.toArray(new FieldDefine[list.size()])); } } } private FieldProcessor getFieldProcessor(Element element) { Object[] arguments = getFieldProcessorArguments(element); String clazz = element.getAttribute("class"); try { if (arguments == null || arguments.length == 0) { return (FieldProcessor) Class.forName(clazz).newInstance(); } Constructor<?>[] constructors = Class.forName(clazz).getConstructors(); for (Constructor<?> constructor : constructors) { if (arguments.length == constructor.getParameterCount()) { return (FieldProcessor) constructor.newInstance(arguments); } } } catch (Exception e) { throw new RuntimeException(e); } return null; } private Object[] getFieldProcessorArguments(Element element) { NodeList nodeList = element.getChildNodes(); List<Object> list = new LinkedList<Object>(); if (nodeList != null && nodeList.getLength() > 0) { int length = nodeList.getLength(); for (int i = 0; i < length; i++) { list.add(nodeList.item(i).getTextContent()); } } return list.toArray(new Object[list.size()]); } }