Toon posts:

[java] probleem met reflectie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een vrij onduidelijk probleem met reflectie. Het lijkt alsof een bepaalde invoke domweg genegeerd wordt, hoewel ik blijf hopen dat ik een domme fout maak. Om te beginnen een interface:

Deze interface is een basis interface voor XML tags, de classes die deze interface implementeren maken allemaal gebruik van deze interface (overigens indirect via een DefaultTagHandler class zodat ik niet voor elke tag alle methodes hoef te implementeren)
Java:
1
2
3
4
5
6
7
public interface TagHandler {
  public void startElement(String uri, String localName, String qName,
                           Attributes attributes);
  public void endElement(String uri, String localName, String qName);
  public void characters( char[] ch, int start,  int length);
  public void init( ResultHandler handler );
}


Verder heb ik een class Tag, in deze class worden alle methodes geinvoked. Een tag instantie is gewoon een wrapper om de te reflecteren klasse heen (met het oog op buffering).

Via een xmlreader roep ik de juiste klasse aan voor het afhandelen van een tag. Nu is het vreemde dat van een bepaalde tag de "endElement" methode niet wordt aangroepen in de gereflecteerde klasse, terwijl in alle overige gereflecteerde classes dat wel het geval is. Er treden geen excepties op in mijn Tag class waar dus het reflecteren plaats vind...

Dus als iemand een idee heeft waar ik waarschijnlijk het probleem moet zoeken, laat het dan gaarne even weten.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Heb je gecontroleerd of er misschien een default implementatie wordt aangeroepen in een superklasse omdat je een tikfout hebt gemaakt in de methode naam?

Dit is een probleem wat je vaak ziet, ook bij Adapters (merkwaardige naam) voor Listeners. Het "override" keyword van C# zorgt ervoor dat de compiler op dit punt meer controles kan uitvoeren.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
ja dat was ook mijn eerste gedachte, dus ik heb ook even direct de interface geimplementeerd, de methodes waren/zijn correct.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Hum, jammer ;) .

Ik ben bang dat je dan toch wat meer code zult moeten laten zien, want zo is de oorzaak helaas denk ik niet af te leiden ...

Heb je al wat gedebugged om te kijken welke methoden er dan precies wel worden aangeroepen?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

Topicstarter
Ik wil wel meer code posten, maar het is zolangzamerhand een groot programma aan het worden, dus het is even lastig downsizen, maar okee, heb je een moment. En na het invoken is het niet echt meer te tracken.

Verwijderd

Topicstarter
XMLElementDispatcher.java
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import java.lang.reflect.*;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import org.xml.sax.helpers.DefaultHandler;

import java.util.List;
import java.util.LinkedList;
import org.hda.common.database.*;

import java.util.Stack;
import java.util.StringTokenizer;

import java.util.Date;



public final class XMLElementDispatcher extends DefaultHandler
    implements ExceptionHandler, ResultHandler {

  private SAXParser parser;

  private Tag current;
  private TagTree cacheTree;

  private String tagBase;
  private String suffix;
  private ResultHandler resultHandler = this;
  private ExceptionHandler exceptionHandler = this;

  private int elementCount;


  private Tag defaultTagHandler;

  public XMLElementDispatcher(String tagBase)
      throws SAXException, ParserConfigurationException {
    this(tagBase, "Tag");
  }

  public XMLElementDispatcher(String tagBase, String suffix)
      throws SAXException, ParserConfigurationException {
    this.suffix = suffix;
    this.tagBase = tagBase;

    SAXParserFactory parserFactory = SAXParserFactory.newInstance();
    parser = parserFactory.newSAXParser();

    try{ defaultTagHandler = new Tag(this,"org.hda.xml","DefaultTagHandler"); }
    catch(Exception e){}
  }

  public void parse(File file) throws IOException, SAXException {
    
    cacheTree = new TagTree();    
    parser.parse(file, this);    
  }




  public void error(SAXParseException e) {
    exceptionHandler.parseError(e);
  }

  public void fatalError(SAXParseException e) {
    exceptionHandler.parseFatalError(e);
  }

  public void warning(SAXParseException e) {
    exceptionHandler.parseWarning(e);
  }


  public void startElement(String uri, String localName, String qName,
                           Attributes attributes) {

    String tagName = transformElementToMethod(qName);
    try {
      current = cacheTree.getTagAt( cacheTree.contains(tagName));
      if(current == null){
        current = new Tag(resultHandler,tagBase, tagName);
        cacheTree.addChild(current);
      }
      current.startElement(uri,localName,qName,attributes);
    }
    catch (Exception e) {
      try{
        current = new Tag(defaultTagHandler, tagName);
        cacheTree.addChild(current);
        current.startElement(uri,localName,qName, attributes);
      }catch (Exception e2) {exceptionHandler.tagException(e2);}
    }
  }



  public void characters(char[] ch, int start, int length) {
    try {
      current.characters( ch, start, length );
    }
    catch (Exception e) {exceptionHandler.tagException(e); }


  }



public void endElement(String uri, String localName, String qName) {
    cacheTree.pointToParent();
    try {
      current.endElement( uri, localName, qName);
    }
    catch (Exception e) {exceptionHandler.tagException(e);}
  }



  protected String transformElementToMethod(String qName) {
    StringBuffer result = new StringBuffer(qName.length()+suffix.length());
    StringTokenizer tokenizer = new StringTokenizer(qName, "-");
    while (tokenizer.hasMoreTokens()) {
      String token = tokenizer.nextToken();
      result.append(Character.toUpperCase(token.charAt(0)));
      result.append(token.substring(1, token.length()));
    }
    result.append(suffix);
    return result.toString();
  }

  public void parseError(SAXParseException e){}
  public void parseFatalError(SAXParseException e){}
  public void parseWarning(SAXParseException e){}
  public void tagException(Exception e){System.out.println(e.getMessage());}

}

Tag.java
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import java.lang.reflect.*;
import org.xml.sax.Attributes;

class Tag {
  private String qualifiedName;
  private String name;
  private Object instance;
  private Method startElement;
  private Method characterElement;
  private Method endElement;
  private ResultHandler handler;

  private final Class[] START_METHOD = {
      String.class,
      String.class,
      String.class,
      Attributes.class
  };
  private final Class[] CHARACTER_METHOD = {
      char[].class,
      Integer.TYPE,
      Integer.TYPE
  };
  private final Class[] END_METHOD = {
      String.class,
      String.class,
      String.class
  };
  private final Class[] INIT_METHOD = {
      ResultHandler.class
  };

  public Tag(Tag tag){
    this.qualifiedName = tag.qualifiedName;
    this.name = tag.name;
    this.instance = tag.instance;
    this.startElement = tag.startElement;
    this.characterElement = tag.characterElement;
    this.endElement = tag.endElement;
    this.handler = tag.handler;
  }
  public Tag(Tag tag, String name){
    this(tag);
  }


  public Tag(ResultHandler handler, String tagBase, String tagName )
      throws NoSuchMethodException, ClassNotFoundException,
      IllegalAccessException, InstantiationException,
      InvocationTargetException {

    tagBase = tagBase.endsWith(".") ? tagBase: tagBase + ".";
    name = tagName;
    qualifiedName = tagBase + tagName;


    Class tagHandler = Class.forName(qualifiedName);
    instance = tagHandler.newInstance();
    startElement = tagHandler.getMethod("startElement", START_METHOD);
    characterElement = tagHandler.getMethod("characters", CHARACTER_METHOD);
    endElement = tagHandler.getMethod("endElement", END_METHOD);
    tagHandler.getMethod("init", INIT_METHOD).invoke(
        instance,new Object[]{handler});
  }

  public boolean equals( String name ){
    return this.name.compareTo(name) == 0 ? true: false;
  }


  public String getQualifiedName(){
    return qualifiedName;
  }
  public String getName(){
    return name;
  }
  public Object getInstance(){
    return instance;
  }
  public Method getStartElement(){
    return startElement;
  }
  public Method getCharacterElement(){
    return characterElement;
  }
  public Method getEndElement(){
    return endElement;
  }

  public void startElement(String uri, String localName,
                           String qName, Attributes attributes) throws
      InvocationTargetException, IllegalAccessException {

    startElement.invoke(instance,
                        new Object[] {uri, localName, qName, attributes});

  }

  public void endElement(String uri,
                         String localName,
                         String qName) throws
      InvocationTargetException, IllegalAccessException {
    endElement.invoke(instance, new Object[] {uri, localName, qName});
    System.out.println("invoking " + instance);
  }

  public void characters(char[] ch, int start,
                         int length) throws
      InvocationTargetException, IllegalAccessException {
    characterElement.invoke(instance, new Object[] {ch,
                            new Integer(start), new Integer(length)});
  }


}

TagNode.java
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.*;

public class TagNode{
  private Tag tag;
  private List childs;
  private TagNode parent;

  public TagNode(TagNode parent, Tag tag ){
    this.tag = tag;
    this.parent = parent;
    childs = new LinkedList();
  }


  public boolean equals(String name){
    return tag.equals(name);
  }

  public int contains( Tag tag ){
    return contains(tag.getName());
  }

  public int contains( String name ){
    for(int i = 0; i < childs.size(); ++i)
      if( ((TagNode)childs.get(i)).getTag().equals(name))
        return i;
    return -1;
  }

  public Tag getTag(){
    return tag;
  }

  public void setTag( Tag tag ){
    this.tag = tag;
  }

  public TagNode addChildTag( Tag tag){
    TagNode child = new TagNode(this, tag);
    childs.add(child);
    return child;
  }

  public TagNode getChild( int index ){
    if(index >= 0 && index < childs.size())
      return (TagNode)childs.get(index);
    return null;
  }

  public TagNode getChild(String name){
    return getChild(contains(name));
  }

  public Tag getChildTag( int index ){
    if(index >= 0 && index < childs.size())
      return ((TagNode)childs.get(index)).getTag();
    return null;
  }

  public Tag getChildTag(String qualifiedName){
    return getChildTag(contains(qualifiedName));
  }
  public TagNode getParent(){
    return parent;
  }  

}

TagTree.java
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TagTree {
  private TagNode root;
  private TagNode position;  

  public TagTree(){
    root =  new TagNode(null, null);
    position = root;
    
  }


  public void addChild(Tag tag ){
    position = position.addChildTag(tag);
  }

  public void pointToParent(){
    position = (position.getParent()!=null)? position.getParent() : position;
  }
 
  public Tag getTagAt(int index){
    TagNode helper = position.getChild(index);
    if(helper == null) return null;
    position = helper;
    return position.getTag();
  }
  public Tag getTag(){
    return position.getTag();
  }
  public int contains(String qualifiedName){
    return position.contains(qualifiedName);
  }
}

TagHandler.java
Java:
1
2
3
4
5
6
7
public interface TagHandler {
  public void startElement(String uri, String localName, String qName,
                           Attributes attributes);
  public void endElement(String uri, String localName, String qName);
  public void characters( char[] ch, int start,  int length);
  public void init( ResultHandler handler );
}


Dit zijn de belangrijkste classes, ik heb een aantal Excptie interface maar gemakshalve niet meegenomen, en een hoop functies eruit gehaald

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
wat meteen opvalt is dat characters met int's werkt maar je geeft er Integers aan door... weet niet of dit ermee iets te maken heeft...

edit:

waarom niet effe log4j installeren of effe debuggen?

ook zou ik een heel pak statics toevoegen want er zit precies wel erg veel duplicate in anders...

[ Voor 44% gewijzigd door hobbit_be op 03-03-2003 13:45 ]


Verwijderd

Topicstarter
hobbit_be:
Zo werkt reflectie: de methode invoke wil dat je een object mee geeft, en een int is geen object. Dat werkt prima.

Ik heb overigens het probleem gevonden, Het ging mis met het cashen, dit is wat er nu veranders is:

XMLElementDispatcher.java
Java:
1
2
3
4
5
6
7
8
public void endElement(String uri, String localName, String qName) {

    try {
      current.endElement( uri, localName, qName);
    }
    catch (Exception e) {exceptionHandler.tagException(e);}
    current = cacheTree.pointToParent();
  }


TagTree.java
Java:
1
2
3
4
  public Tag pointToParent(){
    position = (position.getParent()!=null)? position.getParent() : position;
    return position.getTag();
  }



edit: ----------------------------------------
Oh hobbit_be, waar wil je eigelijk static fields gebruiken? Ik snap niet helemaal wat je bedoeld?

edit2: --------------------------------------
Oh bedoel je in de Tag klasse, want inderdaad die class defenities kunnen static worden...

[ Voor 20% gewijzigd door Verwijderd op 03-03-2003 13:59 ]


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
wel bij die finals in je TAG (die worden dan toch voor elke tag remaakt - tenzij final ook als static werkt?). en moet je voor elke Tag echt een instance voor je handler maken of gewoon 1 keer per keer dat je CacheTree maakt?

edit:
ahem niet gezien dat je TagNode NIET extends (Tag) :) dus je hebt zowieso maar 1 instance - gewoon over gelezen...

edits:
lol net tijdens mijn edit jouw edit... bijna IRC zo :)

[ Voor 31% gewijzigd door hobbit_be op 03-03-2003 14:04 ]


Verwijderd

Topicstarter
Nou als je manieren weet om het sneller te krijgen graag. Want tijdens een uitvoer van 70 seconden is 25 seconden voor de SAXParser en 45 seconden voor mijn dispatcher, dus het mag wat sneller... (maar goed naarmate het xml bestand groter wordt is dat verschil kleiner omdat tags niet meer geinitialiseert hoeven te worden...)

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
waarom gebruik je eigenlijk niet de default org.w3c.dom (Xerces) ? - voor de rest zie ik niet veel ruimte voor optimalisatie...

Verwijderd

Topicstarter
omdat een dom implementatie nogal wat geheugen gebruikt, of rete traag wordt. En bij xml bestanden van boven de 500 mb (database backup) loopt het geheugen dan nogal vol. En snelheid vanwege het feit dat als ik een backup wil terugzetten niet de hele toko een halve dag down is. Nu kan dat in zo'n 10 minuten op een celeron 466, dus met een beetje server gaat dat wat sneller...

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
yikes 500MB aan xml!!! say no more - misschien meer iets voor C++ kan gaan die 10Minuten vast naar <1 min maar ik neem aan dat dat geen optie is :). wel leuk te horen dat er nog mensen zijn die op een goede oude celeren 466 werken :) (okee ik zit op een dual cellie maar toch :)

Verwijderd

Topicstarter
dat kan c++ niet veel sneller hoor

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
als ik tijd had zou ik je graag het tegendeel bewijzen :) maar qua parsing zeker 50 keer sneller (no sweat ;) en als je de data-structuur (ie addChildElement) niet moet veranderen dan kan het nog veel sneller...

Verwijderd

Topicstarter
als de jit goed zijn werk doet, dan is het ook machine code, alleen de initialisitie zal langer duren, maar ik hergebruik objecten, dus dat zit wel goed...
Pagina: 1