爬虫组件分析
- 目录
- 概述
- 需求:
- 设计思路
- 实现思路分析
- 1.ActivityProcessor
- 2.AssociationJsonConverter
- 3.BaseBpmnJsonConverter
- 4.BoundaryEventJsonConverter
- 5.BpmnJsonConverter
- 拓展实现
- 参考资料和推荐阅读
Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.
目录
概述
ActivityProcessor的是一个非常常见的需求。
需求:
设计思路
实现思路分析
1.ActivityProcessor
public interface ActivityProcessor {
public void processFlowElements(FlowElementsContainer container, BpmnModel model, ArrayNode shapesArrayNode,
Map<String, ModelInfo> formKeyMap, Map<String, ModelInfo> decisionTableKeyMap, double subProcessX, double subProcessY);
public void processJsonElements(JsonNode shapesArrayNode, JsonNode modelNode, BaseElement parentElement,
Map<String, JsonNode> shapeMap, Map<String, String> formKeyMap, Map<String, String> decisionTableMap, BpmnModel bpmnModel);
}
2.AssociationJsonConverter
@Override
public void convertToJson(BaseElement baseElement, ActivityProcessor processor, BpmnModel model, FlowElementsContainer container, ArrayNode shapesArrayNode, double subProcessX, double subProcessY) {
Association association = (Association) baseElement;
ObjectNode flowNode = BpmnJsonConverterUtil.createChildShape(association.getId(), STENCIL_ASSOCIATION, 172, 212, 128, 212);
ArrayNode dockersArrayNode = objectMapper.createArrayNode();
ObjectNode dockNode = objectMapper.createObjectNode();
dockNode.put(EDITOR_BOUNDS_X, model.getGraphicInfo(association.getSourceRef()).getWidth() / 2.0);
dockNode.put(EDITOR_BOUNDS_Y, model.getGraphicInfo(association.getSourceRef()).getHeight() / 2.0);
dockersArrayNode.add(dockNode);
List<GraphicInfo> graphicInfoList = model.getFlowLocationGraphicInfo(association.getId());
if (graphicInfoList.size() > 2) {
for (int i = 1; i < graphicInfoList.size() - 1; i++) {
GraphicInfo graphicInfo = graphicInfoList.get(i);
dockNode = objectMapper.createObjectNode();
dockNode.put(EDITOR_BOUNDS_X, graphicInfo.getX());
dockNode.put(EDITOR_BOUNDS_Y, graphicInfo.getY());
dockersArrayNode.add(dockNode);
}
}
GraphicInfo targetGraphicInfo = model.getGraphicInfo(association.getTargetRef());
GraphicInfo flowGraphicInfo = graphicInfoList.get(graphicInfoList.size() - 1);
double diffTopY = Math.abs(flowGraphicInfo.getY() - targetGraphicInfo.getY());
double diffRightX = Math.abs(flowGraphicInfo.getX() - (targetGraphicInfo.getX() + targetGraphicInfo.getWidth()));
double diffBottomY = Math.abs(flowGraphicInfo.getY() - (targetGraphicInfo.getY() + targetGraphicInfo.getHeight()));
dockNode = objectMapper.createObjectNode();
if (diffTopY < 5) {
dockNode.put(EDITOR_BOUNDS_X, targetGraphicInfo.getWidth() / 2.0);
dockNode.put(EDITOR_BOUNDS_Y, 0.0);
} else if (diffRightX < 5) {
dockNode.put(EDITOR_BOUNDS_X, targetGraphicInfo.getWidth());
dockNode.put(EDITOR_BOUNDS_Y, targetGraphicInfo.getHeight() / 2.0);
} else if (diffBottomY < 5) {
dockNode.put(EDITOR_BOUNDS_X, targetGraphicInfo.getWidth() / 2.0);
dockNode.put(EDITOR_BOUNDS_Y, targetGraphicInfo.getHeight());
} else {
dockNode.put(EDITOR_BOUNDS_X, 0.0);
dockNode.put(EDITOR_BOUNDS_Y, targetGraphicInfo.getHeight() / 2.0);
}
dockersArrayNode.add(dockNode);
flowNode.set("dockers", dockersArrayNode);
ArrayNode outgoingArrayNode = objectMapper.createArrayNode();
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(association.getTargetRef()));
flowNode.set("outgoing", outgoingArrayNode);
flowNode.set("target", BpmnJsonConverterUtil.createResourceNode(association.getTargetRef()));
ObjectNode propertiesNode = objectMapper.createObjectNode();
propertiesNode.put(PROPERTY_OVERRIDE_ID, association.getId());
flowNode.set(EDITOR_SHAPE_PROPERTIES, propertiesNode);
shapesArrayNode.add(flowNode);
}
3.BaseBpmnJsonConverter
public abstract class BaseBpmnJsonConverter implements EditorJsonConstants,
StencilConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(BaseBpmnJsonConverter.class);
public static final String NAMESPACE = "http://activiti.com/modeler";
protected ObjectMapper objectMapper = new ObjectMapper();
protected ActivityProcessor processor;
protected BpmnModel model;
protected ObjectNode flowElementNode;
protected double subProcessX;
protected double subProcessY;
protected ArrayNode shapesArrayNode;
public void convertToJson(BaseElement baseElement,
ActivityProcessor processor,
BpmnModel model,
FlowElementsContainer container,
ArrayNode shapesArrayNode,
double subProcessX,
double subProcessY) {
this.model = model;
this.processor = processor;
this.subProcessX = subProcessX;
this.subProcessY = subProcessY;
this.shapesArrayNode = shapesArrayNode;
GraphicInfo graphicInfo = model.getGraphicInfo(baseElement.getId());
String stencilId = null;
if (baseElement instanceof ServiceTask) {
ServiceTask serviceTask = (ServiceTask) baseElement;
if ("mail".equalsIgnoreCase(serviceTask.getType())) {
stencilId = STENCIL_TASK_MAIL;
} else if ("camel".equalsIgnoreCase(serviceTask.getType())) {
stencilId = STENCIL_TASK_CAMEL;
} else if ("mule".equalsIgnoreCase(serviceTask.getType())) {
stencilId = STENCIL_TASK_MULE;
} else if ("dmn".equalsIgnoreCase(serviceTask.getType())) {
stencilId = STENCIL_TASK_DECISION;
} else {
stencilId = getStencilId(baseElement);
}
} else {
stencilId = getStencilId(baseElement);
}
flowElementNode = BpmnJsonConverterUtil.createChildShape(baseElement.getId(),
stencilId,
graphicInfo.getX() - subProcessX + graphicInfo.getWidth(),
graphicInfo.getY() - subProcessY + graphicInfo.getHeight(),
graphicInfo.getX() - subProcessX,
graphicInfo.getY() - subProcessY);
shapesArrayNode.add(flowElementNode);
ObjectNode propertiesNode = objectMapper.createObjectNode();
propertiesNode.put(PROPERTY_OVERRIDE_ID, baseElement.getId());
if (baseElement instanceof FlowElement) {
FlowElement flowElement = (FlowElement) baseElement;
if (StringUtils.isNotEmpty(flowElement.getName())) {
propertiesNode.put(PROPERTY_NAME, flowElement.getName());
}
if (StringUtils.isNotEmpty(flowElement.getDocumentation())) {
propertiesNode.put(PROPERTY_DOCUMENTATION, flowElement.getDocumentation());
}
}
convertElementToJson(propertiesNode, baseElement);
flowElementNode.set(EDITOR_SHAPE_PROPERTIES, propertiesNode);
ArrayNode outgoingArrayNode = objectMapper.createArrayNode();
if (baseElement instanceof FlowNode) {
FlowNode flowNode = (FlowNode) baseElement;
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(sequenceFlow.getId()));
}
for (MessageFlow messageFlow : model.getMessageFlows().values()) {
if (messageFlow.getSourceRef().equals(flowNode.getId())) {
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(messageFlow.getId()));
}
}
}
if (baseElement instanceof Activity) {
Activity activity = (Activity) baseElement;
for (BoundaryEvent boundaryEvent : activity.getBoundaryEvents()) {
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(boundaryEvent.getId()));
}
propertiesNode.put(PROPERTY_ASYNCHRONOUS,
activity.isAsynchronous());
propertiesNode.put(PROPERTY_EXCLUSIVE,
!activity.isNotExclusive());
if (activity.getLoopCharacteristics() != null) {
MultiInstanceLoopCharacteristics loopDef = activity.getLoopCharacteristics();
if (StringUtils.isNotEmpty(loopDef.getLoopCardinality()) || StringUtils.isNotEmpty(loopDef.getInputDataItem()) || StringUtils.isNotEmpty(loopDef.getCompletionCondition())) {
if (!loopDef.isSequential()) {
propertiesNode.put(PROPERTY_MULTIINSTANCE_TYPE,
"Parallel");
} else {
propertiesNode.put(PROPERTY_MULTIINSTANCE_TYPE,
"Sequential");
}
if (StringUtils.isNotEmpty(loopDef.getLoopCardinality())) {
propertiesNode.put(PROPERTY_MULTIINSTANCE_CARDINALITY,
loopDef.getLoopCardinality());
}
if (StringUtils.isNotEmpty(loopDef.getInputDataItem())) {
propertiesNode.put(PROPERTY_MULTIINSTANCE_COLLECTION,
loopDef.getInputDataItem());
}
if (StringUtils.isNotEmpty(loopDef.getElementVariable())) {
propertiesNode.put(PROPERTY_MULTIINSTANCE_VARIABLE,
loopDef.getElementVariable());
}
if (StringUtils.isNotEmpty(loopDef.getCompletionCondition())) {
propertiesNode.put(PROPERTY_MULTIINSTANCE_CONDITION,
loopDef.getCompletionCondition());
}
}
}
if (activity instanceof UserTask) {
BpmnJsonConverterUtil.convertListenersToJson(((UserTask) activity).getTaskListeners(),
false,
propertiesNode);
}
if (CollectionUtils.isNotEmpty(activity.getDataInputAssociations())) {
for (DataAssociation dataAssociation : activity.getDataInputAssociations()) {
if (model.getFlowElement(dataAssociation.getSourceRef()) != null) {
createDataAssociation(dataAssociation,
true,
activity);
}
}
}
if (CollectionUtils.isNotEmpty(activity.getDataOutputAssociations())) {
for (DataAssociation dataAssociation : activity.getDataOutputAssociations()) {
if (model.getFlowElement(dataAssociation.getTargetRef()) != null) {
createDataAssociation(dataAssociation,
false,
activity);
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(dataAssociation.getId()));
}
}
}
}
if (baseElement instanceof FlowElement) {
BpmnJsonConverterUtil.convertListenersToJson(((FlowElement) baseElement).getExecutionListeners(),
true,
propertiesNode);
}
for (Artifact artifact : container.getArtifacts()) {
if (artifact instanceof Association) {
Association association = (Association) artifact;
if (StringUtils.isNotEmpty(association.getSourceRef()) && association.getSourceRef().equals(baseElement.getId())) {
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(association.getId()));
}
}
}
if (baseElement instanceof DataStoreReference) {
for (Process process : model.getProcesses()) {
processDataStoreReferences(process,
baseElement.getId(),
outgoingArrayNode);
}
}
flowElementNode.set("outgoing",
outgoingArrayNode);
}
protected void processDataStoreReferences(FlowElementsContainer container,
String dataStoreReferenceId,
ArrayNode outgoingArrayNode) {
for (FlowElement flowElement : container.getFlowElements()) {
if (flowElement instanceof Activity) {
Activity activity = (Activity) flowElement;
if (CollectionUtils.isNotEmpty(activity.getDataInputAssociations())) {
for (DataAssociation dataAssociation : activity.getDataInputAssociations()) {
if (dataStoreReferenceId.equals(dataAssociation.getSourceRef())) {
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(dataAssociation.getId()));
}
}
}
} else if (flowElement instanceof SubProcess) {
processDataStoreReferences((SubProcess) flowElement,
dataStoreReferenceId,
outgoingArrayNode);
}
}
}
protected void createDataAssociation(DataAssociation dataAssociation,
boolean incoming,
Activity activity) {
String sourceRef = null;
String targetRef = null;
if (incoming) {
sourceRef = dataAssociation.getSourceRef();
targetRef = activity.getId();
} else {
sourceRef = activity.getId();
targetRef = dataAssociation.getTargetRef();
}
ObjectNode flowNode = BpmnJsonConverterUtil.createChildShape(dataAssociation.getId(),
STENCIL_DATA_ASSOCIATION,
172,
212,
128,
212);
ArrayNode dockersArrayNode = objectMapper.createArrayNode();
ObjectNode dockNode = objectMapper.createObjectNode();
dockNode.put(EDITOR_BOUNDS_X,
model.getGraphicInfo(sourceRef).getWidth() / 2.0);
dockNode.put(EDITOR_BOUNDS_Y,
model.getGraphicInfo(sourceRef).getHeight() / 2.0);
dockersArrayNode.add(dockNode);
if (model.getFlowLocationGraphicInfo(dataAssociation.getId()).size() > 2) {
for (int i = 1; i < model.getFlowLocationGraphicInfo(dataAssociation.getId()).size() - 1; i++) {
GraphicInfo graphicInfo = model.getFlowLocationGraphicInfo(dataAssociation.getId()).get(i);
dockNode = objectMapper.createObjectNode();
dockNode.put(EDITOR_BOUNDS_X,
graphicInfo.getX());
dockNode.put(EDITOR_BOUNDS_Y,
graphicInfo.getY());
dockersArrayNode.add(dockNode);
}
}
dockNode = objectMapper.createObjectNode();
dockNode.put(EDITOR_BOUNDS_X,
model.getGraphicInfo(targetRef).getWidth() / 2.0);
dockNode.put(EDITOR_BOUNDS_Y,
model.getGraphicInfo(targetRef).getHeight() / 2.0);
dockersArrayNode.add(dockNode);
flowNode.set("dockers",
dockersArrayNode);
ArrayNode outgoingArrayNode = objectMapper.createArrayNode();
outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(targetRef));
flowNode.set("outgoing",
outgoingArrayNode);
flowNode.set("target",
BpmnJsonConverterUtil.createResourceNode(targetRef));
ObjectNode propertiesNode = objectMapper.createObjectNode();
propertiesNode.put(PROPERTY_OVERRIDE_ID,
dataAssociation.getId());
flowNode.set(EDITOR_SHAPE_PROPERTIES,
propertiesNode);
shapesArrayNode.add(flowNode);
}
4.BoundaryEventJsonConverter
public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
fillJsonTypes(convertersToBpmnMap);
fillBpmnTypes(convertersToJsonMap);
}
public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_TIMER, BoundaryEventJsonConverter.class);
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_ERROR, BoundaryEventJsonConverter.class);
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_SIGNAL, BoundaryEventJsonConverter.class);
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_MESSAGE, BoundaryEventJsonConverter.class);
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_CANCEL, BoundaryEventJsonConverter.class);
convertersToBpmnMap.put(STENCIL_EVENT_BOUNDARY_COMPENSATION, BoundaryEventJsonConverter.class);
}
public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
convertersToJsonMap.put(BoundaryEvent.class, BoundaryEventJsonConverter.class);
}
protected String getStencilId(BaseElement baseElement) {
BoundaryEvent boundaryEvent = (BoundaryEvent) baseElement;
List<EventDefinition> eventDefinitions = boundaryEvent.getEventDefinitions();
if (eventDefinitions.size() != 1) {
// return timer event as default;
return STENCIL_EVENT_BOUNDARY_TIMER;
}
EventDefinition eventDefinition = eventDefinitions.get(0);
if (eventDefinition instanceof ErrorEventDefinition) {
return STENCIL_EVENT_BOUNDARY_ERROR;
} else if (eventDefinition instanceof SignalEventDefinition) {
return STENCIL_EVENT_BOUNDARY_SIGNAL;
} else if (eventDefinition instanceof MessageEventDefinition) {
return STENCIL_EVENT_BOUNDARY_MESSAGE;
} else if (eventDefinition instanceof CancelEventDefinition) {
return STENCIL_EVENT_BOUNDARY_CANCEL;
} else if (eventDefinition instanceof CompensateEventDefinition) {
return STENCIL_EVENT_BOUNDARY_COMPENSATION;
} else {
return STENCIL_EVENT_BOUNDARY_TIMER;
}
}
5.BpmnJsonConverter
public class BpmnJsonConverter implements EditorJsonConstants,
StencilConstants,
ActivityProcessor {
protected static final Logger LOGGER = LoggerFactory.getLogger(BpmnJsonConverter.class);
protected ObjectMapper objectMapper = new ObjectMapper();
protected static Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap = new HashMap<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>>();
protected static Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap = new HashMap<String, Class<? extends BaseBpmnJsonConverter>>();
public final static String MODELER_NAMESPACE = "http://activiti.com/modeler";
protected final static DateFormat defaultFormat = new SimpleDateFormat("yyyyMMddHHmmss");
protected final static DateFormat entFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
static {
// start and end events
StartEventJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
EndEventJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// connectors
SequenceFlowJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
MessageFlowJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
AssociationJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// task types
BusinessRuleTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
MailTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
ManualTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
ReceiveTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
ScriptTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
ServiceTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
UserTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
CallActivityJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
CamelTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
MuleTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
SendTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
DecisionTaskJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// gateways
ExclusiveGatewayJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
InclusiveGatewayJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
ParallelGatewayJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
EventGatewayJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// scope constructs
SubProcessJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
EventSubProcessJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// catch events
CatchEventJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// throw events
ThrowEventJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// boundary events
BoundaryEventJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
// artifacts
TextAnnotationJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
DataStoreJsonConverter.fillTypes(convertersToBpmnMap,
convertersToJsonMap);
}
拓展实现
public static void convertListenersToJson(List<ActivitiListener> listeners, boolean isExecutionListener, ObjectNode propertiesNode) {
String propertyName = null;
String valueName = null;
if (isExecutionListener) {
propertyName = PROPERTY_EXECUTION_LISTENERS;
valueName = "executionListeners";
} else {
propertyName = PROPERTY_TASK_LISTENERS;
valueName = "taskListeners";
}
ObjectNode listenersNode = objectMapper.createObjectNode();
ArrayNode itemsNode = objectMapper.createArrayNode();
for (ActivitiListener listener : listeners) {
ObjectNode propertyItemNode = objectMapper.createObjectNode();
propertyItemNode.put(PROPERTY_LISTENER_EVENT, listener.getEvent());
if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(listener.getImplementationType())) {
propertyItemNode.put(PROPERTY_LISTENER_CLASS_NAME, listener.getImplementation());
} else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(listener.getImplementationType())) {
propertyItemNode.put(PROPERTY_LISTENER_EXPRESSION, listener.getImplementation());
} else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(listener.getImplementationType())) {
propertyItemNode.put(PROPERTY_LISTENER_DELEGATE_EXPRESSION, listener.getImplementation());
}
if (CollectionUtils.isNotEmpty(listener.getFieldExtensions())) {
ArrayNode fieldsArray = objectMapper.createArrayNode();
for (FieldExtension fieldExtension : listener.getFieldExtensions()) {
ObjectNode fieldNode = objectMapper.createObjectNode();
fieldNode.put(PROPERTY_FIELD_NAME, fieldExtension.getFieldName());
if (StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
fieldNode.put(PROPERTY_FIELD_STRING_VALUE, fieldExtension.getStringValue());
}
if (StringUtils.isNotEmpty(fieldExtension.getExpression())) {
fieldNode.put(PROPERTY_FIELD_EXPRESSION, fieldExtension.getExpression());
}
fieldsArray.add(fieldNode);
}
propertyItemNode.set(PROPERTY_LISTENER_FIELDS, fieldsArray);
}
itemsNode.add(propertyItemNode);
}
参考资料和推荐阅读
[1]. https://www.activiti.org/
欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~