Reilander:
Cara, não entendi muito bem sua solução não. Pode até ser boa, mas parece que é usar metralhadora pra matar barata. Queria uma alternativa mais simples.
Valeu!
Vc chegou a olhar a apresentação? Nela eu apresento um exemplo de MouseListener que poderia ser feito. E sim, a solução que mandei não é trivial, mas depois de implementada, fica muito fácil de usar. Olhá a comparação dos códigos abaixo:
Parse de xml com SAX usando o padrão Observer tradicional:
public class WorkflowXMLHandler extends DefaultHandler {
private static String[] actionListTypes = {"onEnter","onLeave","onError","trigger"};
private WorkflowDefinition workflow;
private State currentState;
private List actionList;
private String listType;
private String triggerName;
public void endElement(String uri, String localName, String qName) throws SAXException {
if(localName.equals("state")){
workflow.addState(currentState);
currentState = null;
}
if(isActionList(localName)){
if(listType.equals("onEnter")){
currentState.setOnEnter(actionList);
} else if(listType.equals("onLeave")){
currentState.setOnLeave(actionList);
} else if(listType.equals("onError")){
currentState.setOnError(actionList);
} else if(listType.equals("trigger")){
currentState.addTrigger(triggerName, actionList);
}
}
}
public void startDocument() throws SAXException {
workflow = new WorkflowDefinition();
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(localName.equals("workflow")){
setWorkflowProperties(attributes);
}
if(localName.equals("state")){
setStateAttributes(attributes);
}
if(isActionList(localName)){
actionList = new ArrayList();
listType = localName;
if(listType.equals("trigger"))
triggerName = attributes.getValue("name");
}
if(localName.equals("action")){
createAction(attributes);
}
if(localName.equals("nextState")){
createNextState(attributes);
}
}
private void createNextState(Attributes attributes) {
NextState nextState = new NextState();
nextState.setStateName(attributes.getValue("name"));
nextState.setToCompareValue(attributes.getValue("toCompareValue"));
nextState.setEnterAndLeave("true".equalsIgnoreCase(attributes.getValue("enterAndLeave")));
nextState.setToCompareProperty(attributes.getValue("toCompareProperty"));
nextState.setProperty(attributes.getValue("property"));
String evaluationStrategy = attributes.getValue("evaluationStrategy");
if("GREATTER".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.GREATTER);
else if("LESSER".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.LESSER);
else if("LESSER_EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.LESSER_EQUALS);
else if("GREATTER_EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.GREATTER_EQUALS);
else if("EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.EQUALS);
currentState.addNextState(nextState);
}
private void createAction(Attributes attributes) {
GenericAction action = ActionFactory.createAction(attributes.getValue("name"));
for(int i=0;i<attributes.getLength();i++){
if(!attributes.getLocalName(i).equals("name")){
BeanUtils.setProperty(action, attributes.getLocalName(i), attributes.getValue(i));
}
}
actionList.add(action);
}
private boolean isActionList(String localName) {
return Arrays.binarySearch(actionListTypes, localName) >= 0;
}
private void setStateAttributes(Attributes attributes) {
currentState = new State();
currentState.setName(attributes.getValue("name"));
if(attributes.getValue("isInitialState") != null){
currentState.setInitialState(attributes.getValue("isInitialState").equalsIgnoreCase("true"));
}
if(attributes.getValue("isFinalState") != null){
currentState.setFinalState(attributes.getValue("isFinalState").equalsIgnoreCase("true"));
}
}
private void setWorkflowProperties(Attributes attributes) {
try {
workflow.setWorkflowClass(Class.forName(attributes.getValue("class")));
} catch (ClassNotFoundException e) {
throw new RuntimeException("The workflow class "+attributes.getValue("class")+" not found",e);
}
workflow.setIdAttribute(attributes.getValue("idProperty"));
workflow.setWorkflowId(attributes.getValue("id"));
workflow.setDefaultPersistStrategy("true".equalsIgnoreCase(attributes.getValue("persistDefault")));
}
public WorkflowDefinition getWorkflow(){
return workflow;
}
}
Mesmo parsing, utilizando o padrão MetaObservador:
public class WorkflowJColtraneXMLHandler {
private WorkflowDefinition workflow;
private State currentState;
private List actionList;
@StartDocument
private void startDocument() {
workflow = new WorkflowDefinition();
}
@EndElement(localName="state")
private void addStateToWorkFlow(){
workflow.addState(currentState);
currentState = null;
}
@EndElement(localName="onEnter")
private void addStateOnEnterActionsToState(){
currentState.setOnEnter(actionList);
}
@EndElement(localName="onLeave")
private void addStateOnLeaveActionsToState(){
currentState.setOnLeave(actionList);
}
@EndElement(localName="onError")
private void addStateOnErrorActionsToState(){
currentState.setOnLeave(actionList);
}
@EndElement(localName="trigger")
private void addStateTriggerActionsToState(@Attribute("name") String triggerName){
currentState.addTrigger(triggerName, actionList);
}
@BeforeElement(localName="onEnter||onLeave||onError||trigger", elementDeep = 1)
@StartElement(localName="action")
private void buildOnEnterActions(@AttributeMap Map<String,String> attributes){
createAction(attributes);
}
private void createAction(Map<String,String> attributes) {
GenericAction action = ActionFactory.createAction(attributes.get("name"));
for(String attName:attributes.keySet()){
if(!attName.equals("name")){
BeanUtils.setProperty(action, attName, attributes.get(attName));
}
}
actionList.add(action);
}
@StartElement(localName="onEnter||onLeave||onError||trigger")
private void initializeActionList(){
actionList = new ArrayList();
}
@StartElement(localName="nextState")
private void createNextState(@AttributeMap Map<String,String> attributes) {
NextState nextState = new NextState();
nextState.setStateName(attributes.get("name"));
nextState.setToCompareValue(attributes.get("toCompareValue"));
nextState.setEnterAndLeave("true".equalsIgnoreCase(attributes.get("enterAndLeave")));
nextState.setToCompareProperty(attributes.get("toCompareProperty"));
nextState.setProperty(attributes.get("property"));
String evaluationStrategy = attributes.get("evaluationStrategy");
if("GREATTER".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.GREATTER);
else if("LESSER".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.LESSER);
else if("LESSER_EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.LESSER_EQUALS);
else if("GREATTER_EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.GREATTER_EQUALS);
else if("EQUALS".equals(evaluationStrategy))
nextState.setConditionType(ConditionType.EQUALS);
currentState.addNextState(nextState);
}
@StartElement(localName="state",priority=1)
private void setState(@Attribute("name") String stateName) {
currentState = new State();
currentState.setName(stateName);
}
@StartElement(localName="state",attributes={@ContainAttribute(name="isInitialState")})
private void setInitialStateAttributes(@Attribute("isInitialState") boolean isInitialState) {
currentState.setInitialState(isInitialState);
}
@StartElement(localName="state", attributes={@ContainAttribute(name="isFinalState")})
private void setFinalStateAttributes(@Attribute("isFinalState") boolean isFinalState) {
currentState.setFinalState(isFinalState);
}
@StartElement(localName="workflow")
private void setWorkflowProperties(@Attribute("class") String clazz,@Attribute("idProperty") String idProperty,
@Attribute("id") String id,@Attribute("persistDefault") boolean persistDefault) {
try {
workflow.setWorkflowClass(Class.forName(clazz));
} catch (ClassNotFoundException e) {
throw new RuntimeException("The workflow class "+clazz+" not found",e);
}
workflow.setIdAttribute(idProperty);
workflow.setWorkflowId(id);
workflow.setDefaultPersistStrategy(persistDefault);
}
public WorkflowDefinition getWorkflow(){
return workflow;
}
}
Dê uma olhada como o segundo código fica mais legível, sem tantos blocos if/else aninhados...