├── .gitignore ├── README.md ├── data ├── Fingerprint │ ├── f0001_01.gxl │ ├── f0002_05.gxl │ ├── f0003_10.gxl │ ├── f0004_05.gxl │ ├── f0005_03.gxl │ └── small.xml ├── Letter │ ├── AP1_0050.gxl │ ├── AP1_0051.gxl │ ├── AP1_0052.gxl │ ├── FP1_0085.gxl │ ├── FP1_0086.gxl │ ├── FP1_0087.gxl │ ├── HP1_0073.gxl │ ├── HP1_0074.gxl │ ├── HP1_0075.gxl │ ├── HP1_0076.gxl │ ├── KP1_0085.gxl │ ├── KP1_0086.gxl │ ├── KP1_0087.gxl │ ├── KP1_0088.gxl │ └── small.xml └── Molecules │ ├── 1.gxl │ ├── 15.gxl │ ├── 2.gxl │ ├── 5.gxl │ ├── 7.gxl │ └── small.xml ├── graph-matching-toolkit.jar ├── properties ├── properties_fingerprint.prop ├── properties_letter.prop └── properties_molecules.prop ├── result ├── fingerprint.txt ├── letter.txt └── molecule.txt └── src ├── algorithms ├── BipartiteMatching.java ├── GraphFilterer.java ├── GraphMatching.java ├── GreedyMatching.java ├── HungarianAlgorithm.java └── VolgenantJonker.java ├── nanoxml ├── XMLElement.java └── XMLParseException.java ├── net └── n3 │ └── nanoxml │ ├── CDATAReader.java │ ├── ContentReader.java │ ├── IXMLBuilder.java │ ├── IXMLElement.java │ ├── IXMLEntityResolver.java │ ├── IXMLParser.java │ ├── IXMLReader.java │ ├── IXMLValidator.java │ ├── NonValidator.java │ ├── PIReader.java │ ├── StdXMLBuilder.java │ ├── StdXMLParser.java │ ├── StdXMLReader.java │ ├── ValidatorPlugin.java │ ├── XMLAttribute.java │ ├── XMLElement.java │ ├── XMLEntityResolver.java │ ├── XMLException.java │ ├── XMLParseException.java │ ├── XMLParserFactory.java │ ├── XMLUtil.java │ ├── XMLValidationException.java │ ├── XMLWriter.java │ └── sax │ ├── SAXAdapter.java │ ├── SAXEntityResolver.java │ └── SAXParser.java ├── util ├── AssignmentAndCost.java ├── Bunke.java ├── CentralityInterface.java ├── CostFunction.java ├── DoubleIndex.java ├── Edge.java ├── EditDistance.java ├── FloatingSearch.java ├── FloatingSearch2.java ├── Gene.java ├── GeneticSearch.java ├── Graph.java ├── GraphSet.java ├── IndexAndCost.java ├── MatchingAndCost.java ├── MatrixGenerator.java ├── Node.java ├── ResultPrinter.java ├── ReverseGED.java ├── Swap.java └── TreeNode.java └── xml └── XMLParser.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.jar 3 | .project 4 | .classpath 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graph Matching Toolkit 2 | 3 | **Author:** Riesen Kaspar 4 | 5 | --- 6 | 7 | ## Quick Start 8 | 9 | We recommend the following three steps: 10 | 11 | #### STEP 1: 12 | Unzip the archive `Sources.zip`, integrate the whole framework in an IDE (e.g. Eclipse) and build the project. 13 | 14 | #### STEP 2: 15 | Define a properties file in order to define the parameters of your graph matching task. In the folder `properties` you find three examples of such properties (for more details on these parameters we refer to our paper: 16 | 17 | *K. Riesen, S. Emmenegger and H. Bunke. A Novel Software Toolkit for Graph Edit Distance Computation.. In W.G. Kropatsch et al., editors, Proc. 9th Int. Workshop on Graph Based Representations in Pattern Recognition, LNCS 7877, 142–151, 2013.* 18 | 19 | #### STEP 3: 20 | Run the graph matching as a java application. The main method is in `GraphMatching.java`, the sole program argument is an URL pointing to the properties file (e.g.: `./properties/properties_molecules.prop`) 21 | 22 | --- 23 | 24 | ## Change Log 25 | 26 | Changes to the original code. 27 | 28 | #### 1.1.0 (2017-10-05) `b16d7f4` 29 | * More concise console output. 30 | * Exception handling: easier debug of issues related to parsing the properties files. 31 | * More details in the result file. 32 | * More comments about how to set the properties in `properties_letter.prop`. 33 | 34 | #### 1.0.1 (2017-06-27) `0b51e0f` 35 | * Implemented the cost function for `csvDouble` for attributes in the form `[double, double, ... , double]`. 36 | 37 | #### 1.0.0 (2017-01-30) `e833baa` 38 | * Version provided to me by Kaspar Riesen. 39 | 40 | --- 41 | 42 | ### Discalimer 43 | 44 | Daniele Zambon ([dzambon](https://github.com/dzambon)) is just the owner of the github repository. The author of the source code is Kaspar Riesen. -------------------------------------------------------------------------------- /data/Fingerprint/f0001_01.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 149.00000097.000000193.000000106.000000121.000000118.000000214.000000148.000000134.000000106.000000203.000000118.000000213.000000129.0000000.5144962.601173-0.514496-0.5404200.6782802.396173-0.678280-0.7454190.7682210.876058-0.768221-2.2655350.7399400.832981-0.739940-2.3086110.9986181.518213-0.998618-1.623379 4 | -------------------------------------------------------------------------------- /data/Fingerprint/f0002_05.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 128.00000082.00000056.000000148.00000088.000000151.00000057.000000185.000000115.00000087.00000097.00000089.00000088.000000101.00000086.000000117.00000089.000000134.00000065.000000166.0000000.3589792.774419-0.358979-0.3671740.1104323.030935-0.110432-0.1106570.8000002.214297-0.800000-0.9272950.9922781.695151-0.992278-1.4464410.9847841.396124-0.984784-1.7454690.9982741.629552-0.998274-1.5120410.8944271.107149-0.894427-2.0344440.9216351.969319-0.921635-1.172274 4 | -------------------------------------------------------------------------------- /data/Fingerprint/f0003_10.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 147.000000125.000000171.000000140.000000158.000000142.0000000.8395700.996491-0.839570-2.145101-0.152057-0.1526490.1520572.988943 4 | -------------------------------------------------------------------------------- /data/Fingerprint/f0004_05.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 130.000000115.00000098.000000180.000000120.000000122.000000103.000000123.00000093.000000134.00000088.000000149.00000094.000000164.0000000.5734622.530867-0.573462-0.6107260.0587223.082837-0.058722-0.0587560.7399402.308611-0.739940-0.8329810.9486831.892547-0.948683-1.2490460.9284771.190290-0.928477-1.9513030.9701431.325818-0.970143-1.815775 4 | -------------------------------------------------------------------------------- /data/Fingerprint/f0005_03.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /data/Fingerprint/small.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /data/Letter/AP1_0050.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.3897271.500131.460722.232562.632150.6112350.9442540.9543291.682181.2493 -------------------------------------------------------------------------------- /data/Letter/AP1_0051.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.8653941.325221.232872.628292.393390.8335680.8542661.443192.414331.60016 -------------------------------------------------------------------------------- /data/Letter/AP1_0052.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.7145960.8418641.494972.594862.239240.4670121.138961.594421.707021.63576 -------------------------------------------------------------------------------- /data/Letter/FP1_0085.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.112352.914050.4428150.7013520.7807142.044162.114662.95902 -------------------------------------------------------------------------------- /data/Letter/FP1_0086.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.4413423.366150.8678280.9686330.6421791.999011.015771.711071.696082.53422 -------------------------------------------------------------------------------- /data/Letter/FP1_0087.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.115052.798871.10082-0.02526070.3542262.042441.502861.853492.12.782.20932.34204 -------------------------------------------------------------------------------- /data/Letter/HP1_0073.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.5455243.336131.067760.6804591.920010.6732331.962242.89160.9235691.869462.525481.63045 -------------------------------------------------------------------------------- /data/Letter/HP1_0074.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.133542.916390.4223590.3505481.744920.06940452.052.860.74882.248462.169362.327692.205391.93425 -------------------------------------------------------------------------------- /data/Letter/HP1_0075.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.058243.07940.6390820.5486652.347470.7435172.064183.064850.8396861.91142.473081.71787 -------------------------------------------------------------------------------- /data/Letter/HP1_0076.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.5278823.231420.8449140.5990732.143590.7242.052.86-0.1894421.645572.292341.761072.275251.368 -------------------------------------------------------------------------------- /data/Letter/KP1_0085.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.8199723.130122.303962.988231.356611.165040.591.752.292540.7731762.576192.32793 -------------------------------------------------------------------------------- /data/Letter/KP1_0086.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.225072.570650.4910990.7772630.4053071.672821.710690.643797 -------------------------------------------------------------------------------- /data/Letter/KP1_0087.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.732.872.631512.836590.8278610.1439470.915451.576371.910.630.5116351.947621.978130.307395 -------------------------------------------------------------------------------- /data/Letter/KP1_0088.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.02072.620131.839593.455841.216170.768090.6624481.146022.209790.526307 -------------------------------------------------------------------------------- /data/Letter/small.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /data/Molecules/1.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A 103.73210.25 5 | 6 | B 204.5981-0.25 7 | 8 | B 204.5981-0.25 9 | 10 | 1 11 | 1 12 | 1 -------------------------------------------------------------------------------- /data/Molecules/15.gxl: -------------------------------------------------------------------------------- 1 | 2 | S 502.866-2C 102.866-1C 103.7321-0.5C 102-0.5C 103.73210.5C 104.5981-1C 1020.5 3 | 121112 4 | -------------------------------------------------------------------------------- /data/Molecules/2.gxl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A 103.73210.25 5 | 6 | C 104.5981-0.25 7 | 8 | C 304.5981-0.25 9 | 10 | C 404.5981-0.25 11 | 12 | 1 13 | 1 14 | 1 15 | -------------------------------------------------------------------------------- /data/Molecules/5.gxl: -------------------------------------------------------------------------------- 1 | 2 | C 103.73210.25C 104.5981-0.25S 502.866-0.25S 505.46410.25O 202-0.75O 203.366-1.116O 202.3660.616 3 | 111221 4 | -------------------------------------------------------------------------------- /data/Molecules/7.gxl: -------------------------------------------------------------------------------- 1 | 2 | C 103.73211.25O 204.59811.75O 202.8661.75C 103.73210.25C 102.866-0.25C 104.5981-0.25O 2020.25C 102.866-1.252112111 3 | -------------------------------------------------------------------------------- /data/Molecules/small.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /graph-matching-toolkit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzambon/graph-matching-toolkit/8b3ab3cef2453d52d182af24a28452359eedfedc/graph-matching-toolkit.jar -------------------------------------------------------------------------------- /properties/properties_fingerprint.prop: -------------------------------------------------------------------------------- 1 | ### :::::::::::::::::::::: IMPORTANT INFORMATION ::::::::::::::::::::::::::::::: # 2 | # 3 | # consult the following website (and the corresponding paper) for 4 | # more detailed information about the individual parameters and 5 | # their meanings: 6 | # 7 | # http://www.fhnw.ch/wirtschaft/iwi/gmt 8 | # 9 | ### :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # 10 | 11 | 12 | 13 | ######################################################################################### 14 | # source and target graph set, pathes to the graph and result folder # 15 | ######################################################################################### 16 | source=./data/Fingerprint/small.xml 17 | target=./data/Fingerprint/small.xml 18 | path=./data/Fingerprint/ 19 | result=./result/fingerprint 20 | 21 | 22 | ######################################################################################### 23 | # graph matching paradigm (possible choices are: AStar, Beam, Hungarian, VJ) # 24 | # if "Beam" is chosen, maximum number of open paths s has to be defined # 25 | ######################################################################################### 26 | matching=Hungarian 27 | s= 28 | adj=best 29 | 30 | ######################################################################################### 31 | # cost for node/edge deletions/insertions (both cost values have to be > 0) # 32 | ######################################################################################### 33 | node=1.0 34 | edge=1.0 35 | 36 | 37 | ######################################################################################### 38 | # number of node attributes and the individual names of these attributes # 39 | ######################################################################################### 40 | numOfNodeAttr=0 41 | nodeAttr0= 42 | 43 | 44 | ######################################################################################### 45 | # cost function type per individual node attribute # 46 | # (possible choices are: squared, absolute, discrete, sed) # 47 | # if cost-function=discrete for node attribute i: nodeCostMui and nodeCostNui # 48 | # (non-negative real values) have to be additionally defined # 49 | ######################################################################################### 50 | nodeCostType0= 51 | 52 | ######################################################################################### 53 | # weighting parameters per individual node attribute # 54 | # (min=0, max=1.0; default = 1.0) # 55 | ######################################################################################### 56 | nodeAttr0Importance= 57 | 58 | 59 | ######################################################################################### 60 | # individual node costs are added (multiplyNodeCosts=0) or # 61 | # multiplied (multiplyNodeCosts=1) # 62 | # p-th root is extracted from the combined node cost # 63 | ######################################################################################### 64 | multiplyNodeCosts=0 65 | pNode=1 66 | 67 | 68 | ######################################################################################### 69 | # edges are directed (=0) or undirected (=1) # 70 | ######################################################################################### 71 | undirected=1 72 | 73 | 74 | ######################################################################################### 75 | # number of edge attributes and the individual names of these attributes # 76 | ######################################################################################### 77 | numOfEdgeAttr=1 78 | edgeAttr0=angle 79 | 80 | 81 | ######################################################################################### 82 | # cost function type per individual edge attribute # 83 | # (possible choices are: squared, absolute, discrete, sed) # 84 | # if cost-function=discrete for edge attribute i: nodeCostMui and nodeCostNui # 85 | # (non-negative real values) have to be additionally defined # 86 | ######################################################################################### 87 | edgeCostType0=absolute 88 | 89 | 90 | ######################################################################################### 91 | # weighting parameters per individual edge attribute # 92 | # (min=0, max=1.0; default = 1.0) # 93 | ######################################################################################### 94 | edgeAttr0Importance=1.0 95 | 96 | 97 | ######################################################################################### 98 | # individual edge costs are added (multiplyEdgeCosts=0) or # 99 | # multiplied (multiplyEdgeCosts=1) # 100 | # p-th root is extracted from the combined edge cost # 101 | ######################################################################################### 102 | multiplyEdgeCosts=0 103 | pEdge=1 104 | 105 | 106 | ######################################################################################### 107 | # alpha weights the node and edge costs: # 108 | # alpha * nodeCost; (1-alpha) * edgeCost 109 | ######################################################################################### 110 | alpha=0.2 111 | 112 | 113 | ######################################################################################### 114 | # logging options on the console # 115 | ######################################################################################### 116 | outputGraphs=0 117 | outputEditpath=0 118 | outputCostMatrix=0 119 | outputMatching=0 120 | 121 | 122 | ######################################################################################### 123 | # build similarities from distances or not (possible choices are 0,1,2,3,4) # 124 | ######################################################################################### 125 | simKernel=4 126 | 127 | 128 | -------------------------------------------------------------------------------- /properties/properties_molecules.prop: -------------------------------------------------------------------------------- 1 | ### :::::::::::::::::::::: IMPORTANT INFORMATION ::::::::::::::::::::::::::::::: # 2 | # 3 | # consult the following website (and the corresponding paper) for 4 | # more detailed information about the individual parameters and 5 | # their meanings: 6 | # 7 | # http://www.fhnw.ch/wirtschaft/iwi/gmt 8 | # 9 | ### :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # 10 | 11 | 12 | 13 | ######################################################################################### 14 | # source and target graph set, pathes to the graph and result folder # 15 | ######################################################################################### 16 | source=./data/Molecules/small.xml 17 | target=./data/Molecules/small.xml 18 | path=./data/Molecules/ 19 | result=./result/molecule 20 | 21 | 22 | ######################################################################################### 23 | # graph matching paradigm (possible choices are: AStar, Beam, Hungarian, VJ) # 24 | # if "Beam" is chosen, maximum number of open paths s has to be defined # 25 | ######################################################################################### 26 | matching=Beam 27 | s=10 28 | adj=best 29 | 30 | ######################################################################################### 31 | # cost for node/edge deletions/insertions (both cost values have to be > 0) # 32 | ######################################################################################### 33 | node=3.0 34 | edge=3.0 35 | 36 | 37 | ######################################################################################### 38 | # number of node attributes and the individual names of these attributes # 39 | ######################################################################################### 40 | numOfNodeAttr=2 41 | nodeAttr0=chem 42 | nodeAttr1=charge 43 | 44 | 45 | ######################################################################################### 46 | # cost function type per individual node attribute # 47 | # (possible choices are: squared, absolute, discrete, sed) # 48 | # if cost-function=discrete for node attribute i: nodeCostMui and nodeCostNui # 49 | # (non-negative real values) have to be additionally defined # 50 | ######################################################################################### 51 | nodeCostType0=discrete 52 | nodeCostType1=absolute 53 | nodeCostMu0=0 54 | nodeCostNu0=2 55 | 56 | 57 | ######################################################################################### 58 | # weighting parameters per individual node attribute # 59 | # (min=0, max=1.0; default = 1.0) # 60 | ######################################################################################### 61 | nodeAttr0Importance=1.0 62 | nodeAttr1Importance=0.3 63 | 64 | 65 | ######################################################################################### 66 | # individual node costs are added (multiplyNodeCosts=0) or # 67 | # multiplied (multiplyNodeCosts=1) # 68 | # p-th root is extracted from the combined node cost # 69 | ######################################################################################### 70 | multiplyNodeCosts=0 71 | pNode=1 72 | 73 | 74 | ######################################################################################### 75 | # edges are directed (=0) or undirected (=1) # 76 | ######################################################################################### 77 | undirected=1 78 | 79 | 80 | ######################################################################################### 81 | # number of edge attributes and the individual names of these attributes # 82 | ######################################################################################### 83 | numOfEdgeAttr=1 84 | edgeAttr0=valence 85 | 86 | 87 | ######################################################################################### 88 | # cost function type per individual edge attribute # 89 | # (possible choices are: squared, absolute, discrete, sed) # 90 | # if cost-function=discrete for edge attribute i: nodeCostMui and nodeCostNui # 91 | # (non-negative real values) have to be additionally defined # 92 | ######################################################################################### 93 | edgeCostType0=squared 94 | 95 | 96 | ######################################################################################### 97 | # weighting parameters per individual edge attribute # 98 | # (min=0, max=1.0; default = 1.0) # 99 | ######################################################################################### 100 | edgeAttr0Importance=1.0 101 | 102 | 103 | ######################################################################################### 104 | # individual edge costs are added (multiplyEdgeCosts=0) or # 105 | # multiplied (multiplyEdgeCosts=1) # 106 | # p-th root is extracted from the combined edge cost # 107 | ######################################################################################### 108 | multiplyEdgeCosts=0 109 | pEdge=1 110 | 111 | 112 | ######################################################################################### 113 | # alpha weights the node and edge costs: # 114 | # alpha * nodeCost; (1-alpha) * edgeCost 115 | ######################################################################################### 116 | alpha=0.8 117 | 118 | 119 | ######################################################################################### 120 | # logging options on the console # 121 | ######################################################################################### 122 | outputGraphs=0 123 | outputEditpath=0 124 | outputCostMatrix=0 125 | outputMatching=0 126 | 127 | 128 | ######################################################################################### 129 | # build similarities from distances or not (possible choices are 0,1,2,3,4) # 130 | ######################################################################################### 131 | simKernel=0 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /result/fingerprint.txt: -------------------------------------------------------------------------------- 1 | #*** The properties of the matching *** 2 | #Source graph set: ./data/Fingerprint/small.xml (5 graphs) 3 | #Target graph set: ./data/Fingerprint/small.xml (5 graphs) 4 | #Graph edit distance procedure: Hungarian 5 | #Edge mode: undirected 6 | #Cost for node deletion/insertion: 1.0 7 | #Cost for edge deletion/insertion: 1.0 8 | #Alpha weighting factor between node and edge costs: 0.2 9 | #No attributes for nodes defined 10 | #Edge Attribute 0: angle; Cost Function: absolute; Soft Factor: 1.0 11 | #Individual node costs are added 12 | #Individual edge costs are added 13 | #(Combined node cost)^(1/1.0) 14 | #(Combined edge cost)^(1/1.0) 15 | #Complete Matching Time: 31 16 | #Number of Fails: 0 17 | 18 | *** The similarity matrix exp(-d) *** 19 | 20 | 1.00000 21 | 0.00469 22 | 0.00747 23 | 0.00013 24 | 0.00452 25 | 0.00469 26 | 1.00000 27 | 0.00038 28 | 0.00027 29 | 0.00022 30 | 0.00747 31 | 0.00038 32 | 1.00000 33 | 0.00030 34 | 0.11080 35 | 0.00000 36 | 0.00027 37 | 0.00030 38 | 1.00000 39 | 0.00203 40 | 0.00452 41 | 0.00022 42 | 0.11080 43 | 0.00203 44 | 1.00000 45 | -------------------------------------------------------------------------------- /result/letter.txt: -------------------------------------------------------------------------------- 1 | #*** The properties of the matching *** 2 | #Date of the computation: 2017/10/05 22:48:48 3 | #Source graph set: ./data/Letter/small.xml (14 graphs) 4 | #Target graph set: ./data/Letter/small.xml (14 graphs) 5 | #Graph edit distance procedure: AStar 6 | #Edge mode: undirected 7 | #Cost for node deletion/insertion: 1.0 8 | #Cost for edge deletion/insertion: 1.0 9 | #Alpha weighting factor between node and edge costs: 0.5 10 | #Node attribute 0: x; Cost function: squared; Soft factor: 1.0 11 | #Node attribute 1: y; Cost function: squared; Soft factor: 1.0 12 | #No attributes for edges defined 13 | #Individual node costs are added 14 | #Individual edge costs are added 15 | #(Combined node cost)^(1/2.0) 16 | #(Combined edge cost)^(1/1.0) 17 | #Complete Matching Time: 1019 18 | #Number of Fails: 0 19 | # 20 | #*** The distance matrix *** 21 | # ... data is printed in the following order ((s)ource,(t)arget): 22 | # [d(s1,t1); d(s1,t2); d(s1,t3); ... d(s1,tn); d(s2,t1); d(s2,t2);...] 23 | 0.00000 24 | 2.37285 25 | 2.09029 26 | 3.88027 27 | 3.63818 28 | 4.82475 29 | 4.22378 30 | 5.20565 31 | 4.25018 32 | 4.70879 33 | 5.12088 34 | 2.55093 35 | 4.78994 36 | 3.61331 37 | 2.37285 38 | 0.00000 39 | 2.59939 40 | 3.63108 41 | 3.63731 42 | 3.96681 43 | 2.74904 44 | 5.06333 45 | 3.20240 46 | 4.78936 47 | 4.04073 48 | 3.85995 49 | 4.59207 50 | 3.65110 51 | 2.09029 52 | 2.59939 53 | 0.00000 54 | 2.38192 55 | 3.96838 56 | 3.63232 57 | 4.06463 58 | 5.17180 59 | 4.27213 60 | 4.96104 61 | 5.14114 62 | 2.84647 63 | 5.77015 64 | 3.54006 65 | 3.88027 66 | 3.63108 67 | 2.38192 68 | 0.00000 69 | 3.52663 70 | 3.73963 71 | 4.64060 72 | 4.95994 73 | 4.67718 74 | 5.16994 75 | 5.18475 76 | 2.18477 77 | 5.43969 78 | 3.27894 79 | 3.63818 80 | 3.63731 81 | 3.96838 82 | 3.52663 83 | 0.00000 84 | 4.08654 85 | 3.86320 86 | 4.32387 87 | 4.23885 88 | 4.59630 89 | 4.88230 90 | 4.02616 91 | 4.31384 92 | 3.90727 93 | 4.82475 94 | 3.96681 95 | 3.63232 96 | 3.73963 97 | 4.08654 98 | 0.00000 99 | 4.92406 100 | 3.82113 101 | 4.19845 102 | 5.47131 103 | 4.01677 104 | 4.48006 105 | 5.57435 106 | 4.84058 107 | 4.22378 108 | 2.74904 109 | 4.06463 110 | 4.64060 111 | 3.86320 112 | 4.92406 113 | 0.00000 114 | 4.68477 115 | 2.92590 116 | 3.53426 117 | 4.35088 118 | 4.34072 119 | 4.29939 120 | 4.05049 121 | 5.20565 122 | 5.06333 123 | 5.17180 124 | 4.95994 125 | 4.32387 126 | 3.82113 127 | 4.68477 128 | 0.00000 129 | 4.01447 130 | 3.60248 131 | 4.86256 132 | 5.46361 133 | 4.62840 134 | 5.75099 135 | 4.25018 136 | 3.20240 137 | 4.27213 138 | 4.67718 139 | 4.23885 140 | 4.19845 141 | 2.92590 142 | 4.01447 143 | 0.00000 144 | 3.71126 145 | 3.58640 146 | 5.01396 147 | 4.94431 148 | 4.24092 149 | 4.70879 150 | 4.78936 151 | 4.96104 152 | 5.16994 153 | 4.59630 154 | 5.47131 155 | 3.53426 156 | 3.60248 157 | 3.71126 158 | 0.00000 159 | 4.96693 160 | 5.03621 161 | 5.29815 162 | 5.52505 163 | 5.12088 164 | 4.04073 165 | 5.14114 166 | 5.18475 167 | 4.88230 168 | 4.01677 169 | 4.35088 170 | 4.86256 171 | 3.58640 172 | 4.96693 173 | 0.00000 174 | 4.87061 175 | 5.12926 176 | 4.97878 177 | 2.55093 178 | 3.85995 179 | 2.84647 180 | 2.18477 181 | 4.02616 182 | 4.48006 183 | 4.34072 184 | 5.46361 185 | 5.01396 186 | 5.03621 187 | 4.87061 188 | 0.00000 189 | 4.38209 190 | 2.89478 191 | 4.78994 192 | 4.59207 193 | 5.77015 194 | 5.43969 195 | 4.31384 196 | 5.57435 197 | 4.29939 198 | 4.62840 199 | 4.94431 200 | 5.29815 201 | 5.12926 202 | 4.38209 203 | 0.00000 204 | 4.97006 205 | 3.61331 206 | 3.65110 207 | 3.54006 208 | 3.27894 209 | 3.90727 210 | 4.84058 211 | 4.05049 212 | 5.75099 213 | 4.24092 214 | 5.52505 215 | 4.97878 216 | 2.89478 217 | 4.97006 218 | 0.00000 219 | -------------------------------------------------------------------------------- /result/molecule.txt: -------------------------------------------------------------------------------- 1 | #*** The properties of the matching *** 2 | #Source graph set: ./data/Molecules/small.xml (5 graphs) 3 | #Target graph set: ./data/Molecules/small.xml (5 graphs) 4 | #Graph edit distance procedure: Beam 5 | #s = 10 6 | #Edge mode: undirected 7 | #Cost for node deletion/insertion: 3.0 8 | #Cost for edge deletion/insertion: 3.0 9 | #Alpha weighting factor between node and edge costs: 0.8 10 | #Node attribute 0: chem; Cost function: discrete; mu = 0 nu = 2; Soft factor: 1.0 11 | #Node attribute 1: charge; Cost function: absolute; Soft factor: 0.3 12 | #Edge Attribute 0: valence; Cost Function: squared; Soft Factor: 1.0 13 | #Individual node costs are added 14 | #Individual edge costs are added 15 | #(Combined node cost)^(1/1.0) 16 | #(Combined edge cost)^(1/1.0) 17 | #Complete Matching Time: 58 18 | #Number of Fails: 0 19 | #*** The distance matrix *** 20 | 0.00000 21 | 6.80000 22 | 14.40000 23 | 15.80000 24 | 15.80000 25 | 6.80000 26 | 0.00000 27 | 13.80000 28 | 15.20000 29 | 12.40000 30 | 15.40000 31 | 13.80000 32 | 0.00000 33 | 7.80000 34 | 10.00000 35 | 17.20000 36 | 18.00000 37 | 16.00000 38 | 0.00000 39 | 9.60000 40 | 17.00000 41 | 12.60000 42 | 10.60000 43 | 9.00000 44 | 0.00000 45 | -------------------------------------------------------------------------------- /src/algorithms/BipartiteMatching.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package algorithms; 5 | 6 | /** 7 | * @author riesen 8 | * 9 | */ 10 | public class BipartiteMatching { 11 | 12 | /** 13 | * the matching procedure defined via GUI or properties file 14 | * possible choices are 'Hungarian' or 'VJ' (VolgenantJonker) 15 | */ 16 | private String matching; 17 | 18 | /** 19 | * whether (1) or not (0) the matching found is logged on the console 20 | */ 21 | private int outputMatching; 22 | 23 | 24 | private double assignmentCost = 0; 25 | 26 | public double getAssignmentCost() { 27 | return assignmentCost; 28 | } 29 | 30 | 31 | /** 32 | * @param matching 33 | * @param outputMatching 34 | */ 35 | public BipartiteMatching(String matching, int outputMatching) { 36 | this.matching = matching; 37 | this.outputMatching = outputMatching; 38 | } 39 | 40 | 41 | /** 42 | * @return the optimal matching according to the @param costMatrix 43 | * the matching actually used is defined in the string "matching" 44 | */ 45 | public int[][] getMatching(double[][] costMatrix) { 46 | int[][] assignment = null;; 47 | if (this.matching.equals("VJ") ){ 48 | VolgenantJonker vj = new VolgenantJonker(); 49 | vj.computeAssignment(costMatrix); 50 | int[] solution = vj.rowsol; 51 | assignment = new int[costMatrix.length][2]; 52 | // format the assignment correctly 53 | for (int i = 0; i < solution.length; i++){ 54 | assignment[i][0]=i; 55 | assignment[i][1]=solution[i]; 56 | } 57 | 58 | } else { 59 | HungarianAlgorithm ha = new HungarianAlgorithm(); 60 | assignment = ha.hgAlgorithm(costMatrix); 61 | // this.assignmentCost = ha.hgAlgorithmOnlyCost(costMatrix); 62 | // RiesenMunkres ha = new RiesenMunkres(costMatrix); 63 | // assignment = ha.getMinCostMatching(); 64 | } 65 | 66 | // log the matching on the console 67 | if (this.outputMatching==1){ 68 | System.out.println("\nThe Optimal Matching:"); 69 | for (int k = 0; k < assignment.length; k++){ 70 | System.out.print(assignment[k][0]+" -> "+assignment[k][1]+" "); 71 | } 72 | System.out.println(); 73 | } 74 | 75 | return assignment; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/algorithms/GraphFilterer.java: -------------------------------------------------------------------------------- 1 | package algorithms; 2 | 3 | import java.io.FileInputStream; 4 | 5 | import java.util.Iterator; 6 | import java.util.Properties; 7 | 8 | import util.Graph; 9 | import util.GraphSet; 10 | import xml.XMLParser; 11 | 12 | public class GraphFilterer { 13 | 14 | private GraphSet source; 15 | 16 | public GraphFilterer(String prop) throws Exception { 17 | Properties properties = new Properties(); 18 | properties.load(new FileInputStream(prop)); 19 | System.out.println("Load the source and target graph sets..."); 20 | XMLParser xmlParser = new XMLParser(); 21 | xmlParser.setGraphPath(properties.getProperty("path")); 22 | String sourceString = properties.getProperty("source"); 23 | this.source = xmlParser.parseCXL(sourceString); 24 | 25 | Iterator iter = this.source.iterator(); 26 | int MAX_NUMBER = 150; 27 | int counter = 0; 28 | while (iter.hasNext()){ 29 | Graph g = iter.next(); 30 | if (counter % 2 == 0){ 31 | System.out.println(" "); 32 | } 33 | counter++; 34 | } 35 | 36 | } 37 | 38 | /** 39 | * @param args 40 | */ 41 | public static void main(String[] args) { 42 | try { 43 | GraphFilterer gf = new GraphFilterer("/Users/riesen/Documents/GraphMatchingProject/PropertiesFiles/GREC_Exact.txt"); 44 | } catch (Exception e) { 45 | // TODO Auto-generated catch block 46 | e.printStackTrace(); 47 | } 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/algorithms/GreedyMatching.java: -------------------------------------------------------------------------------- 1 | package algorithms; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.Iterator; 7 | import java.util.LinkedList; 8 | 9 | import util.AssignmentAndCost; 10 | 11 | public class GreedyMatching { 12 | 13 | 14 | 15 | 16 | 17 | 18 | public int[][] getMatching(double[][] cm, boolean shuffle) { 19 | int[][] assignment = new int[cm.length][2]; 20 | int[] usedIndices = new int[cm.length]; 21 | // Arrays.fill(usedIndices, 0); 22 | ArrayList unusedIndices = new ArrayList(); 23 | for (int k = 0; k < cm.length; k++){ 24 | unusedIndices.add(k); 25 | } 26 | if (shuffle){ 27 | Collections.shuffle(unusedIndices); 28 | } 29 | for (int i = 0; i < cm.length; i++){ 30 | int iIndex = unusedIndices.get(i); 31 | int greedyMatch = -1; 32 | double min = Double.MAX_VALUE; 33 | for (int j = 0; j < cm.length; j++){ 34 | if (usedIndices[j] == 0){ 35 | if (cm[iIndex][j] <= min){ 36 | min = cm[iIndex][j]; 37 | greedyMatch = j; 38 | } 39 | } 40 | } 41 | assignment[iIndex][0] = iIndex; 42 | assignment[iIndex][1] = greedyMatch; 43 | usedIndices[greedyMatch] = 1; 44 | } 45 | return assignment; 46 | } 47 | 48 | private void printAssignment(int[][] assignment, double[][] cm) { 49 | System.out.println("The cost matrix: "); 50 | for (int i = 0; i < cm.length; i++){ 51 | for (int j = 0; j < cm.length; j++ ){ 52 | if (cm[i][j]>Double.MAX_VALUE){ 53 | System.out.print("inf\t"); 54 | } else { 55 | System.out.print(cm[i][j]+"\t"); 56 | } 57 | 58 | } 59 | System.out.println(); 60 | } 61 | System.out.println("The Assignment:"); 62 | for (int i = 0; i < assignment.length; i++){ 63 | System.out.println(assignment[i][0] +" --> "+assignment[i][1]); 64 | } 65 | 66 | } 67 | 68 | 69 | 70 | public int[][] getRefinedMatching(double[][] cm) { 71 | int[][] assignment = new int[cm.length][2]; 72 | int[] usedIndicesOfG2 = new int[cm.length]; 73 | int[] usedIndicesOfG1 = new int[cm.length]; 74 | 75 | LinkedList unusedIndicesOfG1 = new LinkedList(); 76 | for (int k = 0; k < cm.length; k++){ 77 | unusedIndicesOfG1.add(k); 78 | } 79 | 80 | Collections.shuffle(unusedIndicesOfG1); 81 | 82 | while (!unusedIndicesOfG1.isEmpty()){ 83 | int iIndex = unusedIndicesOfG1.removeFirst(); 84 | usedIndicesOfG1[iIndex]=1; 85 | int greedyMatch = -1; 86 | double min = Double.MAX_VALUE; 87 | for (int j = 0; j < cm.length; j++){ 88 | if (usedIndicesOfG2[j] == 0){ 89 | if (cm[iIndex][j] <= min){ 90 | min = cm[iIndex][j]; 91 | greedyMatch = j; 92 | } 93 | } 94 | } 95 | 96 | // iIndex-->greedyMatch is minimal is greedyMatch-->iIndex also? 97 | int greedyReverseMatch = -1; 98 | min = Double.MAX_VALUE; 99 | for (int i = 0; i < cm.length; i++){ 100 | if (usedIndicesOfG1[i] == 0){ 101 | if (cm[i][greedyMatch] < min){ 102 | min = cm[i][greedyMatch]; 103 | greedyReverseMatch = i; 104 | } 105 | } 106 | } 107 | if (min < cm[iIndex][greedyMatch]){ 108 | usedIndicesOfG1[iIndex]=0; 109 | assignment[greedyReverseMatch][0] = greedyReverseMatch; 110 | assignment[greedyReverseMatch][1] = greedyMatch; 111 | usedIndicesOfG1[greedyReverseMatch]=1; 112 | usedIndicesOfG2[greedyMatch] = 1; 113 | unusedIndicesOfG1.remove(new Integer(greedyReverseMatch)); 114 | unusedIndicesOfG1.add(iIndex); 115 | } else { 116 | assignment[iIndex][0] = iIndex; 117 | assignment[iIndex][1] = greedyMatch; 118 | usedIndicesOfG2[greedyMatch] = 1; 119 | } 120 | } 121 | return assignment; 122 | } 123 | 124 | 125 | 126 | public int[][] greedySort(double[][] cm, int sSize, int tSize) { 127 | int[][] assignment = new int[sSize][2]; 128 | int[] usedIndicesOfG2 = new int[tSize]; 129 | int[] usedIndicesOfG1 = new int[sSize]; 130 | LinkedList unusedIndicesOfG1 = new LinkedList(); 131 | LinkedList unusedIndicesOfG2 = new LinkedList(); 132 | for (int k = 0; k < sSize; k++){ 133 | unusedIndicesOfG1.add(k); 134 | } 135 | for (int k = 0; k < tSize; k++){ 136 | unusedIndicesOfG2.add(k); 137 | } 138 | LinkedList substitutions = new LinkedList(); 139 | for (int i = 0; i < sSize; i++){ 140 | for (int j = 0; j < tSize; j++){ 141 | AssignmentAndCost aAndc = new AssignmentAndCost(i,j,cm[i][j]); 142 | substitutions.add(aAndc); 143 | } 144 | } 145 | Collections.sort(substitutions); 146 | Iterator iter = substitutions.iterator(); 147 | while (!unusedIndicesOfG1.isEmpty() && !unusedIndicesOfG2.isEmpty()){ 148 | AssignmentAndCost aAndc = iter.next(); 149 | int from = aAndc.getFrom(); 150 | if (usedIndicesOfG1[from]==0){ 151 | int to = aAndc.getTo(); 152 | if (usedIndicesOfG2[to]==0){ 153 | usedIndicesOfG1[from]=1; 154 | usedIndicesOfG2[to]=1; 155 | assignment[from][0] = from; 156 | assignment[from][1] = to; 157 | unusedIndicesOfG1.remove(new Integer(from)); 158 | unusedIndicesOfG2.remove(new Integer(to)); 159 | } 160 | } 161 | } 162 | while (!unusedIndicesOfG1.isEmpty()){ 163 | int from = unusedIndicesOfG1.removeFirst(); 164 | assignment[from][0] = from; 165 | assignment[from][1] = tSize+1; 166 | } 167 | 168 | return assignment; 169 | } 170 | 171 | 172 | 173 | public int[][] getRefinedMatching2(double[][] cm, BipartiteMatching bm) { 174 | int[] usedIndicesOfG2 = new int[cm.length]; 175 | int[] usedIndicesOfG1 = new int[cm.length]; 176 | 177 | LinkedList unusedIndicesOfG1 = new LinkedList(); 178 | for (int k = 0; k < cm.length; k++){ 179 | unusedIndicesOfG1.add(k); 180 | } 181 | 182 | Collections.shuffle(unusedIndicesOfG1); 183 | 184 | while (!unusedIndicesOfG1.isEmpty()){ 185 | int iIndex = unusedIndicesOfG1.removeFirst(); 186 | usedIndicesOfG1[iIndex]=1; 187 | int greedyMatch = -1; 188 | double min = Double.MAX_VALUE; 189 | for (int j = 0; j < cm.length; j++){ 190 | if (usedIndicesOfG2[j] == 0){ 191 | if (cm[iIndex][j] <= min){ 192 | min = cm[iIndex][j]; 193 | greedyMatch = j; 194 | } 195 | } 196 | } 197 | 198 | // iIndex-->greedyMatch is minimal is greedyMatch-->iIndex also? 199 | min = Double.MAX_VALUE; 200 | for (int i = 0; i < cm.length; i++){ 201 | if (usedIndicesOfG1[i] == 0){ 202 | if (cm[i][greedyMatch] < min){ 203 | min = cm[i][greedyMatch]; 204 | } 205 | } 206 | } 207 | if (min >= cm[iIndex][greedyMatch]){ 208 | for (int j = 0; j < cm.length; j++){ 209 | if (j!=greedyMatch){ 210 | cm[iIndex][greedyMatch]=Double.POSITIVE_INFINITY; 211 | cm[greedyMatch][iIndex]=Double.POSITIVE_INFINITY; 212 | } else { 213 | cm[iIndex][greedyMatch]=0.; 214 | cm[greedyMatch][iIndex]=0.; 215 | } 216 | } 217 | } 218 | } 219 | return bm.getMatching(cm); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /src/algorithms/VolgenantJonker.java: -------------------------------------------------------------------------------- 1 | package algorithms; 2 | 3 | class VolgenantJonker { 4 | /************************************************************************ 5 | * 6 | * Code for Linear Assignment Problems Java-Version of the lap.cpp-Algorithm (v 7 | * 1.0) of R. Jonker and A. Volgenant, University of Amsterdam. 8 | * 9 | * "A Shortest Augmenting Path Algorithm for Dense and Sparse Linear Assignment 10 | * Problems," Computing 38, 325-340, 1987 11 | * 12 | *************************************************************************/ 13 | 14 | public VolgenantJonker(){ 15 | 16 | } 17 | 18 | int BIG = 100000; 19 | int[] rowsol; 20 | int[] colsol; 21 | 22 | public double computeAssignment(double[][] costMatrix){ 23 | int dim = costMatrix.length; 24 | rowsol = new int[dim]; 25 | colsol = new int[dim]; 26 | double[] u = new double[dim]; 27 | double[] v = new double[dim]; 28 | return this.lap(dim, costMatrix, rowsol, colsol, u, v); 29 | } 30 | 31 | public double lap(int dim, double[][] assigncost, int[] rowsol, int[] colsol, 32 | double[] u, double[] v) 33 | 34 | // input: 35 | // dim - problem size 36 | // assigncost - cost matrix 37 | // output: 38 | // rowsol - column assigned to row in solution 39 | // -> job i is assigned to worker rowsol[i] 40 | // numeration from 0 on 41 | // colsol - row assigned to column in solution 42 | // u - dual variables, row reduction numbers 43 | // v - dual variables, column reduction numbers 44 | 45 | { 46 | boolean unassignedfound; 47 | int i, imin, numfree = 0, prvnumfree, f, i0, k, freerow; 48 | int[] pred, free; 49 | int j = 0, j1 = 0, j2 = 0, endofpath = 0, last = 0, low = 0, up = 0; 50 | int[] collist, matches; 51 | double[] d; 52 | double min = 0; 53 | double h, umin; 54 | double usubmin, v2; 55 | 56 | free = new int[dim]; // list of unassigned rows. 57 | collist = new int[dim]; // list of columns to be scanned in various 58 | // ways. 59 | matches = new int[dim]; // counts how many times a row could be 60 | // assigned. 61 | d = new double[dim]; // 'cost-distance' in augmenting path calculation. 62 | pred = new int[dim]; // row-predecessor of column in 63 | // augmenting/alternating path. 64 | 65 | // init how many times a row will be assigned in the column reduction. 66 | for (i = 0; i < dim; i++) 67 | matches[i] = 0; 68 | 69 | // COLUMN REDUCTION 70 | for (j = dim - 1; j >= 0; j--) // reverse order gives better results. 71 | { 72 | // find minimum cost over rows. 73 | min = assigncost[0][j]; 74 | imin = 0; 75 | for (i = 1; i < dim; i++) 76 | if (assigncost[i][j] < min) { 77 | min = assigncost[i][j]; 78 | imin = i; 79 | } 80 | v[j] = min; 81 | 82 | if (++matches[imin] == 1) { 83 | // init assignment if minimum row assigned for first time. 84 | rowsol[imin] = j; 85 | colsol[j] = imin; 86 | } else 87 | colsol[j] = -1; // row already assigned, column not assigned. 88 | } 89 | 90 | // REDUCTION TRANSFER 91 | for (i = 0; i < dim; i++) 92 | if (matches[i] == 0) // fill list of unassigned 'free' rows. 93 | free[numfree++] = i; 94 | else if (matches[i] == 1) // transfer reduction from rows that are 95 | // assigned once. 96 | { 97 | j1 = rowsol[i]; 98 | min = BIG; 99 | for (j = 0; j < dim; j++) 100 | if (j != j1) 101 | if (assigncost[i][j] - v[j] < min) 102 | min = assigncost[i][j] - v[j]; 103 | v[j1] = v[j1] - min; 104 | } 105 | 106 | // AUGMENTING ROW REDUCTION 107 | int loopcnt = 0; // do-loop to be done twice. 108 | do { 109 | loopcnt++; 110 | 111 | // scan all free rows. 112 | // in some cases, a free row may be replaced with another one to be 113 | // scanned next. 114 | k = 0; 115 | prvnumfree = numfree; 116 | numfree = 0; // start list of rows still free after augmenting row 117 | // reduction. 118 | while (k < prvnumfree) { 119 | i = free[k]; 120 | k++; 121 | 122 | // find minimum and second minimum reduced cost over columns. 123 | umin = assigncost[i][0] - v[0]; 124 | j1 = 0; 125 | usubmin = BIG; 126 | for (j = 1; j < dim; j++) { 127 | h = assigncost[i][j] - v[j]; 128 | if (h < usubmin) 129 | if (h >= umin) { 130 | usubmin = h; 131 | j2 = j; 132 | } else { 133 | usubmin = umin; 134 | umin = h; 135 | j2 = j1; 136 | j1 = j; 137 | } 138 | } 139 | 140 | i0 = colsol[j1]; 141 | if (umin < usubmin) 142 | // change the reduction of the minimum column to increase 143 | // the minimum 144 | // reduced cost in the row to the subminimum. 145 | v[j1] = v[j1] - (usubmin - umin); 146 | else // minimum and subminimum equal. 147 | if (i0 >= 0) // minimum column j1 is assigned. 148 | { 149 | // swap columns j1 and j2, as j2 may be unassigned. 150 | j1 = j2; 151 | i0 = colsol[j2]; 152 | } 153 | 154 | // (re-)assign i to j1, possibly de-assigning an i0. 155 | rowsol[i] = j1; 156 | colsol[j1] = i; 157 | 158 | if (i0 >= 0) // minimum column j1 assigned earlier. 159 | /* 160 | * BUGFIX: Endless Loop (Fankhauser), right side after && added 161 | */ 162 | if ((umin < usubmin) && ((umin-usubmin)>2*Float.MIN_VALUE)) 163 | // put in current k, and go back to that k. 164 | // continue augmenting path i - j1 with i0. 165 | free[--k] = i0; 166 | else 167 | // no further augmenting reduction possible. 168 | // store i0 in list of free rows for next phase. 169 | free[numfree++] = i0; 170 | } 171 | } while (loopcnt < 2); // repeat once. 172 | 173 | // AUGMENT SOLUTION for each free row. 174 | for (f = 0; f < numfree; f++) { 175 | freerow = free[f]; // start row of augmenting path. 176 | 177 | // Dijkstra shortest path algorithm. 178 | // runs until unassigned column added to shortest path tree. 179 | for (j = 0; j < dim; j++) { 180 | d[j] = assigncost[freerow][j] - v[j]; 181 | pred[j] = freerow; 182 | collist[j] = j; // init column list. 183 | } 184 | 185 | low = 0; // columns in 0..low-1 are ready, now none. 186 | up = 0; // columns in low..up-1 are to be scanned for current 187 | // minimum, now none. 188 | // columns in up..dim-1 are to be considered later to find new 189 | // minimum, 190 | // at this stage the list simply contains all columns 191 | unassignedfound = false; 192 | do { 193 | if (up == low) // no more columns to be scanned for current 194 | // minimum. 195 | { 196 | last = low - 1; 197 | 198 | // scan columns for up..dim-1 to find all indices for which 199 | // new minimum occurs. 200 | // store these indices between low..up-1 (increasing up). 201 | min = d[collist[up++]]; 202 | for (k = up; k < dim; k++) { 203 | j = collist[k]; 204 | h = d[j]; 205 | if (h <= min) { 206 | if (h < min) // new minimum. 207 | { 208 | up = low; // restart list at index low. 209 | min = h; 210 | } 211 | // new index with same minimum, put on undex up, and 212 | // extend list. 213 | collist[k] = collist[up]; 214 | collist[up++] = j; 215 | } 216 | } 217 | 218 | // check if any of the minimum columns happens to be 219 | // unassigned. 220 | // if so, we have an augmenting path right away. 221 | for (k = low; k < up; k++) 222 | if (colsol[collist[k]] < 0) { 223 | endofpath = collist[k]; 224 | unassignedfound = true; 225 | break; 226 | } 227 | } 228 | 229 | if (!unassignedfound) { 230 | // update 'distances' between freerow and all unscanned 231 | // columns, via next scanned column. 232 | j1 = collist[low]; 233 | low++; 234 | i = colsol[j1]; 235 | h = assigncost[i][j1] - v[j1] - min; 236 | 237 | for (k = up; k < dim; k++) { 238 | j = collist[k]; 239 | v2 = assigncost[i][j] - v[j] - h; 240 | if (v2 < d[j]) { 241 | pred[j] = i; 242 | if (v2 == min) // new column found at same minimum 243 | // value 244 | if (colsol[j] < 0) { 245 | // if unassigned, shortest augmenting path 246 | // is complete. 247 | endofpath = j; 248 | unassignedfound = true; 249 | break; 250 | } 251 | // else add to list to be scanned right away. 252 | else { 253 | collist[k] = collist[up]; 254 | collist[up++] = j; 255 | } 256 | d[j] = v2; 257 | } 258 | } 259 | } 260 | } while (!unassignedfound); 261 | 262 | // update column prices. 263 | for (k = 0; k <= last; k++) { 264 | j1 = collist[k]; 265 | v[j1] = v[j1] + d[j1] - min; 266 | } 267 | 268 | // reset row and column assignments along the alternating path. 269 | do { 270 | i = pred[endofpath]; 271 | colsol[endofpath] = i; 272 | j1 = endofpath; 273 | endofpath = rowsol[i]; 274 | rowsol[i] = j1; 275 | } while (i != freerow); 276 | } 277 | 278 | // calculate optimal cost. 279 | double lapcost = 0; 280 | for (i = 0; i < dim; i++) { 281 | j = rowsol[i]; 282 | u[i] = assigncost[i][j] - v[j]; 283 | lapcost = lapcost + assigncost[i][j]; 284 | } 285 | 286 | // free reserved memory. 287 | pred = null; 288 | free = null; 289 | collist = null; 290 | matches = null; 291 | d = null; 292 | 293 | return lapcost; 294 | } 295 | 296 | 297 | public int[] getAssignment(){ 298 | return this.rowsol; 299 | } 300 | 301 | 302 | public int computeAssignment(int[][] matrix) { 303 | // TODO Auto-generated method stub 304 | return 0; 305 | } 306 | 307 | 308 | 309 | } 310 | -------------------------------------------------------------------------------- /src/nanoxml/XMLParseException.java: -------------------------------------------------------------------------------- 1 | /* XMLParseException.java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/03/24 10:27:59 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 Lite. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | *****************************************************************************/ 28 | 29 | 30 | package nanoxml; 31 | 32 | 33 | /** 34 | * @author kriesen 35 | */ 36 | public class XMLParseException 37 | extends RuntimeException 38 | { 39 | 40 | /** 41 | * Indicates that no line number has been associated with this exception. 42 | */ 43 | public static final int NO_LINE = -1; 44 | 45 | 46 | /** 47 | * The line number in the source code where the error occurred, or 48 | * NO_LINE if the line number is unknown. 49 | * 50 | *
Invariants:
51 | *
  • lineNr > 0 || lineNr == NO_LINE 52 | *
53 | */ 54 | private int lineNr; 55 | 56 | 57 | /** 58 | * Creates an exception. 59 | * 60 | * @param name The name of the element where the error is located. 61 | * @param message A message describing what went wrong. 62 | * 63 | *
Preconditions:
64 | *
  • message != null 65 | *
66 | * 67 | *
Postconditions:
68 | *
  • getLineNr() => NO_LINE 69 | *
70 | */ 71 | public XMLParseException(String name, 72 | String message) 73 | { 74 | super("XML Parse Exception during parsing of " 75 | + ((name == null) ? "the XML definition" 76 | : ("a " + name + " element")) 77 | + ": " + message); 78 | this.lineNr = XMLParseException.NO_LINE; 79 | } 80 | 81 | 82 | /** 83 | * Creates an exception. 84 | * 85 | * @param name The name of the element where the error is located. 86 | * @param lineNr The number of the line in the input. 87 | * @param message A message describing what went wrong. 88 | * 89 | *
Preconditions:
90 | *
  • message != null 91 | *
  • lineNr > 0 92 | *
93 | * 94 | *
Postconditions:
95 | *
  • getLineNr() => lineNr 96 | *
97 | */ 98 | public XMLParseException(String name, 99 | int lineNr, 100 | String message) 101 | { 102 | super("XML Parse Exception during parsing of " 103 | + ((name == null) ? "the XML definition" 104 | : ("a " + name + " element")) 105 | + " at line " + lineNr + ": " + message); 106 | this.lineNr = lineNr; 107 | } 108 | 109 | 110 | /** 111 | * Where the error occurred, or NO_LINE if the line number is unknown. 112 | * @see nanoxml.XMLParseException#NO_LINE 113 | * @uml.property name="lineNr" 114 | */ 115 | public int getLineNr() 116 | { 117 | return this.lineNr; 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/CDATAReader.java: -------------------------------------------------------------------------------- 1 | /* CDATAReader.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | 35 | 36 | /** 37 | * @author kriesen 38 | */ 39 | class CDATAReader 40 | extends Reader 41 | { 42 | 43 | /** 44 | * The encapsulated reader. 45 | */ 46 | private IXMLReader reader; 47 | 48 | 49 | /** 50 | * Saved char. 51 | */ 52 | private char savedChar; 53 | 54 | 55 | /** 56 | * True if the end of the stream has been reached. 57 | */ 58 | private boolean atEndOfData; 59 | 60 | 61 | /** 62 | * Creates the reader. 63 | * 64 | * @param reader the encapsulated reader 65 | */ 66 | CDATAReader(IXMLReader reader) 67 | { 68 | this.reader = reader; 69 | this.savedChar = 0; 70 | this.atEndOfData = false; 71 | } 72 | 73 | 74 | /** 75 | * Cleans up the object when it's destroyed. 76 | */ 77 | protected void finalize() 78 | throws Throwable 79 | { 80 | this.reader = null; 81 | super.finalize(); 82 | } 83 | 84 | 85 | /** 86 | * Reads a block of data. 87 | * 88 | * @param buffer where to put the read data 89 | * @param offset first position in buffer to put the data 90 | * @param size maximum number of chars to read 91 | * 92 | * @return the number of chars read, or -1 if at EOF 93 | * 94 | * @throws java.io.IOException 95 | * if an error occurred reading the data 96 | */ 97 | public int read(char[] buffer, 98 | int offset, 99 | int size) 100 | throws IOException 101 | { 102 | int charsRead = 0; 103 | 104 | if (this.atEndOfData) { 105 | return -1; 106 | } 107 | 108 | if ((offset + size) > buffer.length) { 109 | size = buffer.length - offset; 110 | } 111 | 112 | while (charsRead < size) { 113 | char ch = this.savedChar; 114 | 115 | if (ch == 0) { 116 | ch = this.reader.read(); 117 | } else { 118 | this.savedChar = 0; 119 | } 120 | 121 | if (ch == ']') { 122 | char ch2 = this.reader.read(); 123 | 124 | if (ch2 == ']') { 125 | char ch3 = this.reader.read(); 126 | 127 | if (ch3 == '>') { 128 | this.atEndOfData = true; 129 | break; 130 | } 131 | 132 | this.savedChar = ch2; 133 | this.reader.unread(ch3); 134 | } else { 135 | this.reader.unread(ch2); 136 | } 137 | } 138 | buffer[charsRead] = ch; 139 | charsRead++; 140 | } 141 | 142 | if (charsRead == 0) { 143 | charsRead = -1; 144 | } 145 | 146 | return charsRead; 147 | } 148 | 149 | 150 | /** 151 | * Skips remaining data and closes the stream. 152 | * 153 | * @throws java.io.IOException 154 | * if an error occurred reading the data 155 | */ 156 | public void close() 157 | throws IOException 158 | { 159 | while (! this.atEndOfData) { 160 | char ch = this.savedChar; 161 | 162 | if (ch == 0) { 163 | ch = this.reader.read(); 164 | } else { 165 | this.savedChar = 0; 166 | } 167 | 168 | if (ch == ']') { 169 | char ch2 = this.reader.read(); 170 | 171 | if (ch2 == ']') { 172 | char ch3 = this.reader.read(); 173 | 174 | if (ch3 == '>') { 175 | break; 176 | } 177 | 178 | this.savedChar = ch2; 179 | this.reader.unread(ch3); 180 | } else { 181 | this.reader.unread(ch2); 182 | } 183 | } 184 | } 185 | 186 | this.atEndOfData = true; 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/ContentReader.java: -------------------------------------------------------------------------------- 1 | /* ContentReader.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | 35 | 36 | /** 37 | * @author kriesen 38 | */ 39 | class ContentReader 40 | extends Reader 41 | { 42 | 43 | /** 44 | * The encapsulated reader. 45 | */ 46 | private IXMLReader reader; 47 | 48 | 49 | /** 50 | * Buffer. 51 | */ 52 | private String buffer; 53 | 54 | 55 | /** 56 | * Pointer into the buffer. 57 | */ 58 | private int bufferIndex; 59 | 60 | 61 | /** 62 | * The entity resolver. 63 | */ 64 | private IXMLEntityResolver resolver; 65 | 66 | 67 | /** 68 | * Creates the reader. 69 | * 70 | * @param reader the encapsulated reader 71 | * @param resolver the entity resolver 72 | * @param buffer data that has already been read from reader 73 | */ 74 | ContentReader(IXMLReader reader, 75 | IXMLEntityResolver resolver, 76 | String buffer) 77 | { 78 | this.reader = reader; 79 | this.resolver = resolver; 80 | this.buffer = buffer; 81 | this.bufferIndex = 0; 82 | } 83 | 84 | 85 | /** 86 | * Cleans up the object when it's destroyed. 87 | */ 88 | protected void finalize() 89 | throws Throwable 90 | { 91 | this.reader = null; 92 | this.resolver = null; 93 | this.buffer = null; 94 | super.finalize(); 95 | } 96 | 97 | 98 | /** 99 | * Reads a block of data. 100 | * 101 | * @param outputBuffer where to put the read data 102 | * @param offset first position in buffer to put the data 103 | * @param size maximum number of chars to read 104 | * 105 | * @return the number of chars read, or -1 if at EOF 106 | * 107 | * @throws java.io.IOException 108 | * if an error occurred reading the data 109 | */ 110 | public int read(char[] outputBuffer, 111 | int offset, 112 | int size) 113 | throws IOException 114 | { 115 | try { 116 | int charsRead = 0; 117 | int bufferLength = this.buffer.length(); 118 | 119 | if ((offset + size) > outputBuffer.length) { 120 | size = outputBuffer.length - offset; 121 | } 122 | 123 | while (charsRead < size) { 124 | String str = ""; 125 | char ch; 126 | 127 | if (this.bufferIndex >= bufferLength) { 128 | str = XMLUtil.read(this.reader, '&'); 129 | ch = str.charAt(0); 130 | } else { 131 | ch = this.buffer.charAt(this.bufferIndex); 132 | this.bufferIndex++; 133 | outputBuffer[charsRead] = ch; 134 | charsRead++; 135 | continue; // don't interprete chars in the buffer 136 | } 137 | 138 | if (ch == '<') { 139 | this.reader.unread(ch); 140 | break; 141 | } 142 | 143 | if ((ch == '&') && (str.length() > 1)) { 144 | if (str.charAt(1) == '#') { 145 | ch = XMLUtil.processCharLiteral(str); 146 | } else { 147 | XMLUtil.processEntity(str, this.reader, this.resolver); 148 | continue; 149 | } 150 | } 151 | 152 | outputBuffer[charsRead] = ch; 153 | charsRead++; 154 | } 155 | 156 | if (charsRead == 0) { 157 | charsRead = -1; 158 | } 159 | 160 | return charsRead; 161 | } catch (XMLParseException e) { 162 | throw new IOException(e.getMessage()); 163 | } 164 | } 165 | 166 | 167 | /** 168 | * Skips remaining data and closes the stream. 169 | * 170 | * @throws java.io.IOException 171 | * if an error occurred reading the data 172 | */ 173 | public void close() 174 | throws IOException 175 | { 176 | try { 177 | int bufferLength = this.buffer.length(); 178 | 179 | for (;;) { 180 | String str = ""; 181 | char ch; 182 | 183 | if (this.bufferIndex >= bufferLength) { 184 | str = XMLUtil.read(this.reader, '&'); 185 | ch = str.charAt(0); 186 | } else { 187 | ch = this.buffer.charAt(this.bufferIndex); 188 | this.bufferIndex++; 189 | continue; // don't interprete chars in the buffer 190 | } 191 | 192 | if (ch == '<') { 193 | this.reader.unread(ch); 194 | break; 195 | } 196 | 197 | if ((ch == '&') && (str.length() > 1)) { 198 | if (str.charAt(1) != '#') { 199 | XMLUtil.processEntity(str, this.reader, this.resolver); 200 | } 201 | } 202 | } 203 | } catch (XMLParseException e) { 204 | throw new IOException(e.getMessage()); 205 | } 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/IXMLBuilder.java: -------------------------------------------------------------------------------- 1 | /* IXMLBuilder.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | 35 | 36 | /** 37 | * NanoXML uses IXMLBuilder to construct the XML data structure it retrieved 38 | * from its data source. You can supply your own builder or you can use the 39 | * default builder of NanoXML. 40 | *

41 | * If a method of the builder throws an exception, the parsing is aborted and 42 | * {@link net.n3.nanoxml.IXMLParser#parse} throws an 43 | * {@link net.n3.nanoxml.XMLException} which encasulates the original 44 | * exception. 45 | * 46 | * @see net.n3.nanoxml.IXMLParser 47 | * 48 | * @author Marc De Scheemaecker 49 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $ 50 | */ 51 | public interface IXMLBuilder 52 | { 53 | 54 | /** 55 | * This method is called before the parser starts processing its input. 56 | * 57 | * @param systemID the system ID of the XML data source. 58 | * @param lineNr the line on which the parsing starts. 59 | * 60 | * @throws java.lang.Exception 61 | * If an exception occurred while processing the event. 62 | */ 63 | public void startBuilding(String systemID, 64 | int lineNr) 65 | throws Exception; 66 | 67 | 68 | /** 69 | * This method is called when a processing instruction is encountered. 70 | * A PI with a reserved target ("xml" with any case) is never reported. 71 | * 72 | * @param target the processing instruction target. 73 | * @param reader the method can retrieve the parameter of the PI from this 74 | * reader. You may close the reader before reading all its 75 | * data and you cannot read too much data. 76 | * 77 | * @throws java.lang.Exception 78 | * If an exception occurred while processing the event. 79 | */ 80 | public void newProcessingInstruction(String target, 81 | Reader reader) 82 | throws Exception; 83 | 84 | 85 | /** 86 | * This method is called when a new XML element is encountered. 87 | * 88 | * @see #endElement 89 | * 90 | * @param name the name of the element. 91 | * @param nsPrefix the prefix used to identify the namespace. If no 92 | * namespace has been specified, this parameter is null. 93 | * @param nsURI the URI associated with the namespace. If no 94 | * namespace has been specified, or no URI is 95 | * associated with nsPrefix, this parameter is null. 96 | * @param systemID the system ID of the XML data source. 97 | * @param lineNr the line in the source where the element starts. 98 | * 99 | * @throws java.lang.Exception 100 | * If an exception occurred while processing the event. 101 | */ 102 | public void startElement(String name, 103 | String nsPrefix, 104 | String nsURI, 105 | String systemID, 106 | int lineNr) 107 | throws Exception; 108 | 109 | 110 | /** 111 | * This method is called when a new attribute of an XML element is 112 | * encountered. 113 | * 114 | * @param key the key (name) of the attribute. 115 | * @param nsPrefix the prefix used to identify the namespace. If no 116 | * namespace has been specified, this parameter is null. 117 | * @param nsURI the URI associated with the namespace. If no 118 | * namespace has been specified, or no URI is 119 | * associated with nsPrefix, this parameter is null. 120 | * @param value the value of the attribute. 121 | * @param type the type of the attribute. If no type is known, 122 | * "CDATA" is returned. 123 | * 124 | * @throws java.lang.Exception 125 | * If an exception occurred while processing the event. 126 | */ 127 | public void addAttribute(String key, 128 | String nsPrefix, 129 | String nsURI, 130 | String value, 131 | String type) 132 | throws Exception; 133 | 134 | 135 | /** 136 | * This method is called when the attributes of an XML element have been 137 | * processed. 138 | * 139 | * @see #startElement 140 | * @see #addAttribute 141 | * 142 | * @param name the name of the element. 143 | * @param nsPrefix the prefix used to identify the namespace. If no 144 | * namespace has been specified, this parameter is null. 145 | * @param nsURI the URI associated with the namespace. If no 146 | * namespace has been specified, or no URI is 147 | * associated with nsPrefix, this parameter is null. 148 | * 149 | * @throws java.lang.Exception 150 | * If an exception occurred while processing the event. 151 | */ 152 | public void elementAttributesProcessed(String name, 153 | String nsPrefix, 154 | String nsURI) 155 | throws Exception; 156 | 157 | 158 | /** 159 | * This method is called when the end of an XML elemnt is encountered. 160 | * 161 | * @see #startElement 162 | * 163 | * @param name the name of the element. 164 | * @param nsPrefix the prefix used to identify the namespace. If no 165 | * namespace has been specified, this parameter is null. 166 | * @param nsURI the URI associated with the namespace. If no 167 | * namespace has been specified, or no URI is 168 | * associated with nsPrefix, this parameter is null. 169 | * 170 | * @throws java.lang.Exception 171 | * If an exception occurred while processing the event. 172 | */ 173 | public void endElement(String name, 174 | String nsPrefix, 175 | String nsURI) 176 | throws Exception; 177 | 178 | 179 | /** 180 | * This method is called when a PCDATA element is encountered. A Java 181 | * reader is supplied from which you can read the data. The reader will 182 | * only read the data of the element. You don't need to check for 183 | * boundaries. If you don't read the full element, the rest of the data 184 | * is skipped. You also don't have to care about entities: they are 185 | * resolved by the parser. 186 | * 187 | * @param reader the method can retrieve the data from this reader. You 188 | * may close the reader before reading all its data and you 189 | * cannot read too much data. 190 | * @param systemID the system ID of the XML data source. 191 | * @param lineNr the line in the source where the element starts. 192 | * 193 | * @throws java.lang.Exception 194 | * If an exception occurred while processing the event. 195 | */ 196 | public void addPCData(Reader reader, 197 | String systemID, 198 | int lineNr) 199 | throws Exception; 200 | 201 | 202 | /** 203 | * Returns the result of the building process. This method is called just 204 | * before the parse method of IXMLParser returns. 205 | * 206 | * @see net.n3.nanoxml.IXMLParser#parse 207 | * 208 | * @return the result of the building process. 209 | * 210 | * @throws java.lang.Exception 211 | * If an exception occurred while processing the event. 212 | */ 213 | public Object getResult() 214 | throws Exception; 215 | 216 | } 217 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/IXMLEntityResolver.java: -------------------------------------------------------------------------------- 1 | /* IXMLEntityResolver.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.util.Hashtable; 33 | import java.io.Reader; 34 | import java.io.StringReader; 35 | 36 | 37 | /** 38 | * An IXMLEntityResolver resolves entities. 39 | * 40 | * @author Marc De Scheemaecker 41 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $ 42 | */ 43 | public interface IXMLEntityResolver 44 | { 45 | 46 | /** 47 | * Adds an internal entity. 48 | * 49 | * @param name the name of the entity. 50 | * @param value the value of the entity. 51 | */ 52 | public void addInternalEntity(String name, 53 | String value); 54 | 55 | 56 | /** 57 | * Adds an external entity. 58 | * 59 | * @param name the name of the entity. 60 | * @param publicID the public ID of the entity, which may be null. 61 | * @param systemID the system ID of the entity. 62 | */ 63 | public void addExternalEntity(String name, 64 | String publicID, 65 | String systemID); 66 | 67 | 68 | /** 69 | * Returns a Java reader containing the value of an entity. 70 | * 71 | * @param xmlReader the current NanoXML reader. 72 | * @param name the name of the entity. 73 | * 74 | * @return the reader, or null if the entity could not be resolved. 75 | * 76 | * @throws net.n3.nanoxml.XMLParseException 77 | * If an exception occurred while resolving the entity. 78 | */ 79 | public Reader getEntity(IXMLReader xmlReader, 80 | String name) 81 | throws XMLParseException; 82 | 83 | 84 | /** 85 | * Returns true if an entity is external. 86 | * 87 | * @param name the name of the entity. 88 | */ 89 | public boolean isExternalEntity(String name); 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/IXMLParser.java: -------------------------------------------------------------------------------- 1 | /* IXMLParser.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.IOException; 33 | 34 | 35 | /** 36 | * @author kriesen 37 | */ 38 | public interface IXMLParser 39 | { 40 | 41 | /** 42 | * Sets the reader from which the parser retrieves its data. 43 | * @param reader the reader. 44 | * @uml.property name="reader" 45 | */ 46 | public void setReader(IXMLReader reader); 47 | 48 | 49 | /** 50 | * Returns the reader from which the parser retrieves its data. 51 | * 52 | * @return the reader. 53 | */ 54 | public IXMLReader getReader(); 55 | 56 | 57 | /** 58 | * Sets the builder which creates the logical structure of the XML data. 59 | * @param builder the builder. 60 | * @uml.property name="builder" 61 | */ 62 | public void setBuilder(IXMLBuilder builder); 63 | 64 | 65 | /** 66 | * Returns the builder which creates the logical structure of the XML data. 67 | * 68 | * @return the builder. 69 | */ 70 | public IXMLBuilder getBuilder(); 71 | 72 | 73 | /** 74 | * Sets the validator that validates the XML data. 75 | * @param validator the validator. 76 | * @uml.property name="validator" 77 | */ 78 | public void setValidator(IXMLValidator validator); 79 | 80 | 81 | /** 82 | * Returns the validator that validates the XML data. 83 | * 84 | * @return the validator. 85 | */ 86 | public IXMLValidator getValidator(); 87 | 88 | 89 | /** 90 | * Sets the entity resolver. 91 | * @param resolver the non-null resolver. 92 | * @uml.property name="resolver" 93 | */ 94 | public void setResolver(IXMLEntityResolver resolver); 95 | 96 | 97 | /** 98 | * Returns the entity resolver. 99 | * 100 | * @return the non-null resolver. 101 | */ 102 | public IXMLEntityResolver getResolver(); 103 | 104 | 105 | /** 106 | * Parses the data and lets the builder create the logical data structure. 107 | * The method returns the result of getResult of the builder. if an 108 | * error occurred while reading or parsing the data, the method may throw 109 | * an XMLException. 110 | * 111 | * @see net.n3.nanoxml.IXMLBuilder#getResult 112 | * 113 | * @return the logical structure built by the builder. 114 | * 115 | * @throws net.n3.nanoxml.XMLException 116 | * if an error occurred reading or parsing the data 117 | */ 118 | public Object parse() 119 | throws XMLException; 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/IXMLReader.java: -------------------------------------------------------------------------------- 1 | /* IXMLReader.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | import java.io.FileNotFoundException; 35 | import java.net.MalformedURLException; 36 | 37 | 38 | /** 39 | * @author kriesen 40 | */ 41 | public interface IXMLReader 42 | { 43 | 44 | /** 45 | * Reads a character. 46 | * 47 | * @return the character 48 | * 49 | * @throws java.io.IOException 50 | * If no character could be read. 51 | */ 52 | public char read() 53 | throws IOException; 54 | 55 | 56 | /** 57 | * Returns true if the current stream has no more characters left to be 58 | * read. 59 | * 60 | * @throws java.io.IOException 61 | * If an I/O error occurred. 62 | */ 63 | public boolean atEOFOfCurrentStream() 64 | throws IOException; 65 | 66 | 67 | /** 68 | * Returns true if there are no more characters left to be read. 69 | * 70 | * @throws java.io.IOException 71 | * If an I/O error occurred. 72 | */ 73 | public boolean atEOF() 74 | throws IOException; 75 | 76 | 77 | /** 78 | * Pushes the last character read back to the stream. 79 | * 80 | * @param ch the character to push back. 81 | * 82 | * @throws java.io.IOException 83 | * If an I/O error occurred. 84 | */ 85 | public void unread(char ch) 86 | throws IOException; 87 | 88 | 89 | /** 90 | * Returns the line number of the data in the current stream. 91 | */ 92 | public int getLineNr(); 93 | 94 | 95 | /** 96 | * Opens a stream from a public and system ID. 97 | * 98 | * @param publicID the public ID, which may be null. 99 | * @param systemID the system ID, which is never null. 100 | * 101 | * @throws java.net.MalformedURLException 102 | * If the system ID does not contain a valid URL. 103 | * @throws java.io.FileNotFoundException 104 | * If the system ID refers to a local file which does not exist. 105 | * @throws java.io.IOException 106 | * If an error occurred opening the stream. 107 | */ 108 | public Reader openStream(String publicID, 109 | String systemID) 110 | throws MalformedURLException, 111 | FileNotFoundException, 112 | IOException; 113 | 114 | 115 | /** 116 | * Starts a new stream from a Java reader. The new stream is used 117 | * temporary to read data from. If that stream is exhausted, control 118 | * returns to the "parent" stream. 119 | * 120 | * @param reader the reader to read the new data from. 121 | */ 122 | public void startNewStream(Reader reader); 123 | 124 | 125 | /** 126 | * Starts a new stream from a Java reader. The new stream is used 127 | * temporary to read data from. If that stream is exhausted, control 128 | * returns to the parent stream. 129 | * 130 | * @param reader the non-null reader to read the new data from 131 | * @param isInternalEntity true if the reader is produced by resolving 132 | * an internal entity 133 | */ 134 | public void startNewStream(Reader reader, 135 | boolean isInternalEntity); 136 | 137 | 138 | /** 139 | * Returns the current "level" of the stream on the stack of streams. 140 | */ 141 | public int getStreamLevel(); 142 | 143 | 144 | /** 145 | * Sets the system ID of the current stream. 146 | * @param systemID the system ID. 147 | * @throws java.net.MalformedURLException If the system ID does not contain a valid URL. 148 | * @uml.property name="systemID" 149 | */ 150 | public void setSystemID(String systemID) 151 | throws MalformedURLException; 152 | 153 | 154 | /** 155 | * Sets the public ID of the current stream. 156 | * @param publicID the public ID. 157 | * @uml.property name="publicID" 158 | */ 159 | public void setPublicID(String publicID); 160 | 161 | 162 | /** 163 | * Returns the current system ID. 164 | * @uml.property name="systemID" 165 | */ 166 | public String getSystemID(); 167 | 168 | 169 | /** 170 | * Returns the current public ID. 171 | * @uml.property name="publicID" 172 | */ 173 | public String getPublicID(); 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/IXMLValidator.java: -------------------------------------------------------------------------------- 1 | /* IXMLValidator.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | import java.util.Properties; 35 | 36 | 37 | /** 38 | * @author kriesen 39 | */ 40 | public interface IXMLValidator 41 | { 42 | 43 | /** 44 | * Sets the parameter entity resolver. 45 | * @param resolver the entity resolver. 46 | * @uml.property name="parameterEntityResolver" 47 | */ 48 | public void setParameterEntityResolver(IXMLEntityResolver resolver); 49 | 50 | 51 | /** 52 | * Returns the parameter entity resolver. 53 | * 54 | * @return the entity resolver. 55 | */ 56 | public IXMLEntityResolver getParameterEntityResolver(); 57 | 58 | 59 | /** 60 | * Parses the DTD. The validator object is responsible for reading the 61 | * full DTD. 62 | * 63 | * @param publicID the public ID, which may be null. 64 | * @param reader the reader to read the DTD from. 65 | * @param entityResolver the entity resolver. 66 | * @param external true if the DTD is external. 67 | * 68 | * @throws java.lang.Exception 69 | * If something went wrong. 70 | */ 71 | public void parseDTD(String publicID, 72 | IXMLReader reader, 73 | IXMLEntityResolver entityResolver, 74 | boolean external) 75 | throws Exception; 76 | 77 | 78 | /** 79 | * Indicates that an element has been started. 80 | * 81 | * @param name the name of the element. 82 | * @param systemId the system ID of the XML data of the element. 83 | * @param lineNr the line number in the XML data of the element. 84 | * 85 | * @throws java.lang.Exception 86 | * If the element could not be validated. 87 | */ 88 | public void elementStarted(String name, 89 | String systemId, 90 | int lineNr) 91 | throws Exception; 92 | 93 | 94 | /** 95 | * Indicates that the current element has ended. 96 | * 97 | * @param name the name of the element. 98 | * @param systemId the system ID of the XML data of the element. 99 | * @param lineNr the line number in the XML data of the element. 100 | * 101 | * @throws java.lang.Exception 102 | * If the element could not be validated. 103 | */ 104 | public void elementEnded(String name, 105 | String systemId, 106 | int lineNr) 107 | throws Exception; 108 | 109 | 110 | /** 111 | * Indicates that an attribute has been added to the current element. 112 | * 113 | * @param key the name of the attribute. 114 | * @param value the value of the attribute. 115 | * @param systemId the system ID of the XML data of the element. 116 | * @param lineNr the line number in the XML data of the element. 117 | * 118 | * @throws java.lang.Exception 119 | * If the attribute could not be validated. 120 | */ 121 | public void attributeAdded(String key, 122 | String value, 123 | String systemId, 124 | int lineNr) 125 | throws Exception; 126 | 127 | 128 | /** 129 | * This method is called when the attributes of an XML element have been 130 | * processed. 131 | * If there are attributes with a default value which have not been 132 | * specified yet, they have to be put into extraAttributes. 133 | * 134 | * @param name the name of the element. 135 | * @param extraAttributes where to put extra attributes. 136 | * @param systemId the system ID of the XML data of the element. 137 | * @param lineNr the line number in the XML data of the element. 138 | * 139 | * @throws java.lang.Exception 140 | * if the element could not be validated. 141 | */ 142 | public void elementAttributesProcessed(String name, 143 | Properties extraAttributes, 144 | String systemId, 145 | int lineNr) 146 | throws Exception; 147 | 148 | 149 | /** 150 | * Indicates that a new #PCDATA element has been encountered. 151 | * 152 | * @param systemId the system ID of the XML data of the element. 153 | * @param lineNr the line number in the XML data of the element. 154 | * 155 | * @throws java.lang.Exception 156 | * if the element could not be validated. 157 | */ 158 | public void PCDataAdded(String systemId, 159 | int lineNr) 160 | throws Exception; 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/PIReader.java: -------------------------------------------------------------------------------- 1 | /* PIReader.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.Reader; 33 | import java.io.IOException; 34 | 35 | 36 | /** 37 | * @author kriesen 38 | */ 39 | class PIReader 40 | extends Reader 41 | { 42 | 43 | /** 44 | * The encapsulated reader. 45 | */ 46 | private IXMLReader reader; 47 | 48 | 49 | /** 50 | * True if the end of the stream has been reached. 51 | */ 52 | private boolean atEndOfData; 53 | 54 | 55 | /** 56 | * Creates the reader. 57 | * 58 | * @param reader the encapsulated reader 59 | */ 60 | PIReader(IXMLReader reader) 61 | { 62 | this.reader = reader; 63 | this.atEndOfData = false; 64 | } 65 | 66 | 67 | /** 68 | * Cleans up the object when it's destroyed. 69 | */ 70 | protected void finalize() 71 | throws Throwable 72 | { 73 | this.reader = null; 74 | super.finalize(); 75 | } 76 | 77 | 78 | /** 79 | * Reads a block of data. 80 | * 81 | * @param buffer where to put the read data 82 | * @param offset first position in buffer to put the data 83 | * @param size maximum number of chars to read 84 | * 85 | * @return the number of chars read, or -1 if at EOF 86 | * 87 | * @throws java.io.IOException 88 | * if an error occurred reading the data 89 | */ 90 | public int read(char[] buffer, 91 | int offset, 92 | int size) 93 | throws IOException 94 | { 95 | if (this.atEndOfData) { 96 | return -1; 97 | } 98 | 99 | int charsRead = 0; 100 | 101 | if ((offset + size) > buffer.length) { 102 | size = buffer.length - offset; 103 | } 104 | 105 | while (charsRead < size) { 106 | char ch = this.reader.read(); 107 | 108 | if (ch == '?') { 109 | char ch2 = this.reader.read(); 110 | 111 | if (ch2 == '>') { 112 | this.atEndOfData = true; 113 | break; 114 | } 115 | 116 | this.reader.unread(ch2); 117 | } 118 | 119 | buffer[charsRead] = ch; 120 | charsRead++; 121 | } 122 | 123 | if (charsRead == 0) { 124 | charsRead = -1; 125 | } 126 | 127 | return charsRead; 128 | } 129 | 130 | 131 | /** 132 | * Skips remaining data and closes the stream. 133 | * 134 | * @throws java.io.IOException 135 | * if an error occurred reading the data 136 | */ 137 | public void close() 138 | throws IOException 139 | { 140 | while (! this.atEndOfData) { 141 | char ch = this.reader.read(); 142 | 143 | if (ch == '?') { 144 | char ch2 = this.reader.read(); 145 | 146 | if (ch2 == '>') { 147 | this.atEndOfData = true; 148 | } 149 | } 150 | } 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLAttribute.java: -------------------------------------------------------------------------------- 1 | /* XMLAttribute.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | /** 33 | * @author kriesen 34 | */ 35 | class XMLAttribute 36 | { 37 | 38 | /** 39 | * The full name of the attribute. 40 | */ 41 | private String fullName; 42 | 43 | 44 | /** 45 | * The short name of the attribute. 46 | */ 47 | private String name; 48 | 49 | 50 | /** 51 | * The namespace URI of the attribute. 52 | */ 53 | private String namespace; 54 | 55 | 56 | /** 57 | * The value of the attribute. 58 | */ 59 | private String value; 60 | 61 | 62 | /** 63 | * The type of the attribute. 64 | */ 65 | private String type; 66 | 67 | 68 | /** 69 | * Creates a new attribute. 70 | * 71 | * @param fullName the non-null full name 72 | * @param name the non-null short name 73 | * @param namespace the namespace URI, which may be null 74 | * @param value the value of the attribute 75 | * @param type the type of the attribute 76 | */ 77 | XMLAttribute(String fullName, 78 | String name, 79 | String namespace, 80 | String value, 81 | String type) 82 | { 83 | this.fullName = fullName; 84 | this.name = name; 85 | this.namespace = namespace; 86 | this.value = value; 87 | this.type = type; 88 | } 89 | 90 | 91 | /** 92 | * Returns the full name of the attribute. 93 | * @uml.property name="fullName" 94 | */ 95 | String getFullName() 96 | { 97 | return this.fullName; 98 | } 99 | 100 | 101 | /** 102 | * Returns the short name of the attribute. 103 | * @uml.property name="name" 104 | */ 105 | String getName() 106 | { 107 | return this.name; 108 | } 109 | 110 | 111 | /** 112 | * Returns the namespace of the attribute. 113 | * @uml.property name="namespace" 114 | */ 115 | String getNamespace() 116 | { 117 | return this.namespace; 118 | } 119 | 120 | 121 | /** 122 | * Returns the value of the attribute. 123 | * @uml.property name="value" 124 | */ 125 | String getValue() 126 | { 127 | return this.value; 128 | } 129 | 130 | 131 | /** 132 | * Sets the value of the attribute. 133 | * @param value the new value. 134 | * @uml.property name="value" 135 | */ 136 | void setValue(String value) 137 | { 138 | this.value = value; 139 | } 140 | 141 | 142 | /** 143 | * Returns the type of the attribute. 144 | * @param type the new type. 145 | * @uml.property name="type" 146 | */ 147 | String getType() 148 | { 149 | return this.type; 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLEntityResolver.java: -------------------------------------------------------------------------------- 1 | /* XMLEntityResolver.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.util.Hashtable; 33 | import java.io.Reader; 34 | import java.io.StringReader; 35 | 36 | 37 | /** 38 | * An XMLEntityResolver resolves entities. 39 | * 40 | * @author Marc De Scheemaecker 41 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $ 42 | */ 43 | public class XMLEntityResolver 44 | implements IXMLEntityResolver 45 | { 46 | 47 | /** 48 | * The entities. 49 | */ 50 | private Hashtable entities; 51 | 52 | 53 | /** 54 | * Initializes the resolver. 55 | */ 56 | public XMLEntityResolver() 57 | { 58 | this.entities = new Hashtable(); 59 | this.entities.put("amp", "&"); 60 | this.entities.put("quot", """); 61 | this.entities.put("apos", "'"); 62 | this.entities.put("lt", "<"); 63 | this.entities.put("gt", ">"); 64 | } 65 | 66 | 67 | /** 68 | * Cleans up the object when it's destroyed. 69 | */ 70 | protected void finalize() 71 | throws Throwable 72 | { 73 | this.entities.clear(); 74 | this.entities = null; 75 | super.finalize(); 76 | } 77 | 78 | 79 | /** 80 | * Adds an internal entity. 81 | * 82 | * @param name the name of the entity. 83 | * @param value the value of the entity. 84 | */ 85 | public void addInternalEntity(String name, 86 | String value) 87 | { 88 | if (! this.entities.containsKey(name)) { 89 | this.entities.put(name, value); 90 | } 91 | } 92 | 93 | 94 | /** 95 | * Adds an external entity. 96 | * 97 | * @param name the name of the entity. 98 | * @param publicID the public ID of the entity, which may be null. 99 | * @param systemID the system ID of the entity. 100 | */ 101 | public void addExternalEntity(String name, 102 | String publicID, 103 | String systemID) 104 | { 105 | if (! this.entities.containsKey(name)) { 106 | this.entities.put(name, new String[] { publicID, systemID } ); 107 | } 108 | } 109 | 110 | 111 | /** 112 | * Returns a Java reader containing the value of an entity. 113 | * 114 | * @param xmlReader the current XML reader 115 | * @param name the name of the entity. 116 | * 117 | * @return the reader, or null if the entity could not be resolved. 118 | */ 119 | public Reader getEntity(IXMLReader xmlReader, 120 | String name) 121 | throws XMLParseException 122 | { 123 | Object obj = this.entities.get(name); 124 | 125 | if (obj == null) { 126 | return null; 127 | } else if (obj instanceof java.lang.String) { 128 | return new StringReader((String)obj); 129 | } else { 130 | String[] id = (String[]) obj; 131 | return this.openExternalEntity(xmlReader, id[0], id[1]); 132 | } 133 | } 134 | 135 | 136 | /** 137 | * Returns true if an entity is external. 138 | * 139 | * @param name the name of the entity. 140 | */ 141 | public boolean isExternalEntity(String name) 142 | { 143 | Object obj = this.entities.get(name); 144 | return ! (obj instanceof java.lang.String); 145 | } 146 | 147 | 148 | /** 149 | * Opens an external entity. 150 | * 151 | * @param xmlReader the current XML reader 152 | * @param publicID the public ID, which may be null 153 | * @param systemID the system ID 154 | * 155 | * @return the reader, or null if the reader could not be created/opened 156 | */ 157 | protected Reader openExternalEntity(IXMLReader xmlReader, 158 | String publicID, 159 | String systemID) 160 | throws XMLParseException 161 | { 162 | String parentSystemID = xmlReader.getSystemID(); 163 | 164 | try { 165 | return xmlReader.openStream(publicID, systemID); 166 | } catch (Exception e) { 167 | throw new XMLParseException(parentSystemID, 168 | xmlReader.getLineNr(), 169 | "Could not open external entity " 170 | + "at system ID: " + systemID); 171 | } 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLException.java: -------------------------------------------------------------------------------- 1 | /* XMLException.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | import java.io.PrintStream; 32 | import java.io.PrintWriter; 33 | 34 | 35 | /** 36 | * @author kriesen 37 | */ 38 | public class XMLException 39 | extends Exception 40 | { 41 | 42 | /** 43 | * The message of the exception. 44 | */ 45 | private String msg; 46 | 47 | 48 | /** 49 | * The system ID of the XML data where the exception occurred. 50 | */ 51 | private String systemID; 52 | 53 | 54 | /** 55 | * The line number in the XML data where the exception occurred. 56 | */ 57 | private int lineNr; 58 | 59 | 60 | /** 61 | * Encapsulated exception. 62 | */ 63 | private Exception encapsulatedException; 64 | 65 | 66 | /** 67 | * Creates a new exception. 68 | * 69 | * @param msg the message of the exception. 70 | */ 71 | public XMLException(String msg) 72 | { 73 | this(null, -1, null, msg, false); 74 | } 75 | 76 | 77 | /** 78 | * Creates a new exception. 79 | * 80 | * @param e the encapsulated exception. 81 | */ 82 | public XMLException(Exception e) 83 | { 84 | this(null, -1, e, "Nested Exception", false); 85 | } 86 | 87 | 88 | /** 89 | * Creates a new exception. 90 | * 91 | * @param systemID the system ID of the XML data where the exception 92 | * occurred 93 | * @param lineNr the line number in the XML data where the exception 94 | * occurred. 95 | * @param e the encapsulated exception. 96 | */ 97 | public XMLException(String systemID, 98 | int lineNr, 99 | Exception e) 100 | { 101 | this(systemID, lineNr, e, "Nested Exception", true); 102 | } 103 | 104 | 105 | /** 106 | * Creates a new exception. 107 | * 108 | * @param systemID the system ID of the XML data where the exception 109 | * occurred 110 | * @param lineNr the line number in the XML data where the exception 111 | * occurred. 112 | * @param msg the message of the exception. 113 | */ 114 | public XMLException(String systemID, 115 | int lineNr, 116 | String msg) 117 | { 118 | this(systemID, lineNr, null, msg, true); 119 | } 120 | 121 | 122 | /** 123 | * Creates a new exception. 124 | * 125 | * @param systemID the system ID from where the data came 126 | * @param lineNr the line number in the XML data where the exception 127 | * occurred. 128 | * @param e the encapsulated exception. 129 | * @param msg the message of the exception. 130 | * @param reportParams true if the systemID, lineNr and e params need to be 131 | * appended to the message 132 | */ 133 | public XMLException(String systemID, 134 | int lineNr, 135 | Exception e, 136 | String msg, 137 | boolean reportParams) 138 | { 139 | super(XMLException.buildMessage(systemID, lineNr, e, msg, 140 | reportParams)); 141 | this.systemID = systemID; 142 | this.lineNr = lineNr; 143 | this.encapsulatedException = e; 144 | this.msg = XMLException.buildMessage(systemID, lineNr, e, msg, 145 | reportParams); 146 | } 147 | 148 | 149 | /** 150 | * Builds the exception message 151 | * 152 | * @param systemID the system ID from where the data came 153 | * @param lineNr the line number in the XML data where the exception 154 | * occurred. 155 | * @param e the encapsulated exception. 156 | * @param msg the message of the exception. 157 | * @param reportParams true if the systemID, lineNr and e params need to be 158 | * appended to the message 159 | */ 160 | private static String buildMessage(String systemID, 161 | int lineNr, 162 | Exception e, 163 | String msg, 164 | boolean reportParams) 165 | { 166 | String str = msg; 167 | 168 | if (reportParams) { 169 | if (systemID != null) { 170 | str += ", SystemID='" + systemID + "'"; 171 | } 172 | 173 | if (lineNr >= 0) { 174 | str += ", Line=" + lineNr; 175 | } 176 | 177 | if (e != null) { 178 | str += ", Exception: " + e; 179 | } 180 | } 181 | 182 | return str; 183 | } 184 | 185 | 186 | /** 187 | * Cleans up the object when it's destroyed. 188 | */ 189 | protected void finalize() 190 | throws Throwable 191 | { 192 | this.systemID = null; 193 | this.encapsulatedException = null; 194 | super.finalize(); 195 | } 196 | 197 | 198 | /** 199 | * Returns the system ID of the XML data where the exception occurred. If there is no system ID known, null is returned. 200 | * @uml.property name="systemID" 201 | */ 202 | public String getSystemID() 203 | { 204 | return this.systemID; 205 | } 206 | 207 | 208 | /** 209 | * Returns the line number in the XML data where the exception occurred. If there is no line number known, -1 is returned. 210 | * @uml.property name="lineNr" 211 | */ 212 | public int getLineNr() 213 | { 214 | return this.lineNr; 215 | } 216 | 217 | 218 | /** 219 | * Returns the encapsulated exception, or null if no exception is 220 | * encapsulated. 221 | */ 222 | public Exception getException() 223 | { 224 | return this.encapsulatedException; 225 | } 226 | 227 | 228 | /** 229 | * Dumps the exception stack to a print writer. 230 | * 231 | * @param writer the print writer 232 | */ 233 | public void printStackTrace(PrintWriter writer) 234 | { 235 | super.printStackTrace(writer); 236 | 237 | if (this.encapsulatedException != null) { 238 | writer.println("*** Nested Exception:"); 239 | this.encapsulatedException.printStackTrace(writer); 240 | } 241 | } 242 | 243 | 244 | /** 245 | * Dumps the exception stack to an output stream. 246 | * 247 | * @param stream the output stream 248 | */ 249 | public void printStackTrace(PrintStream stream) 250 | { 251 | super.printStackTrace(stream); 252 | 253 | if (this.encapsulatedException != null) { 254 | stream.println("*** Nested Exception:"); 255 | this.encapsulatedException.printStackTrace(stream); 256 | } 257 | } 258 | 259 | 260 | /** 261 | * Dumps the exception stack to System.err. 262 | */ 263 | public void printStackTrace() 264 | { 265 | super.printStackTrace(); 266 | 267 | if (this.encapsulatedException != null) { 268 | System.err.println("*** Nested Exception:"); 269 | this.encapsulatedException.printStackTrace(); 270 | } 271 | } 272 | 273 | 274 | /** 275 | * Returns a string representation of the exception. 276 | */ 277 | public String toString() 278 | { 279 | return this.msg; 280 | } 281 | 282 | } 283 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLParseException.java: -------------------------------------------------------------------------------- 1 | /* XMLParseException.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | /** 33 | * An XMLParseException is thrown when the XML passed to the XML parser is not 34 | * well-formed. 35 | * 36 | * @author Marc De Scheemaecker 37 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $ 38 | */ 39 | public class XMLParseException 40 | extends XMLException 41 | { 42 | 43 | /** 44 | * Creates a new exception. 45 | * 46 | * @param msg the message of the exception. 47 | */ 48 | public XMLParseException(String msg) 49 | { 50 | super(msg); 51 | } 52 | 53 | 54 | /** 55 | * Creates a new exception. 56 | * 57 | * @param systemID the system ID from where the data came 58 | * @param lineNr the line number in the XML data where the exception 59 | * occurred. 60 | * @param msg the message of the exception. 61 | */ 62 | public XMLParseException(String systemID, 63 | int lineNr, 64 | String msg) 65 | { 66 | super(systemID, lineNr, null, msg, true); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLParserFactory.java: -------------------------------------------------------------------------------- 1 | /* XMLParserFactory.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.IOException; 33 | 34 | 35 | /** 36 | * Creates an XML parser. 37 | * 38 | * @author Marc De Scheemaecker 39 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $ 40 | */ 41 | public class XMLParserFactory 42 | { 43 | 44 | /** 45 | * The class name of the default XML parser. 46 | */ 47 | public static final String DEFAULT_CLASS = "net.n3.nanoxml.StdXMLParser"; 48 | 49 | 50 | /** 51 | * The Java properties key of the XML parser class name. 52 | */ 53 | public static final String CLASS_KEY = "net.n3.nanoxml.XMLParser"; 54 | 55 | 56 | /** 57 | * Creates a default parser. 58 | * 59 | * @see #DEFAULT_CLASS 60 | * @see #CLASS_KEY 61 | * 62 | * @return the non-null parser. 63 | * 64 | * @throws java.lang.ClassNotFoundException 65 | * if the class of the parser or validator could not be found. 66 | * @throws java.lang.InstantiationException 67 | * if the parser could not be created 68 | * @throws java.lang.IllegalAccessException 69 | * if the parser could not be created 70 | */ 71 | public static IXMLParser createDefaultXMLParser() 72 | throws ClassNotFoundException, 73 | InstantiationException, 74 | IllegalAccessException 75 | { 76 | String className = System.getProperty(XMLParserFactory.CLASS_KEY, 77 | XMLParserFactory.DEFAULT_CLASS); 78 | return XMLParserFactory.createXMLParser(className, 79 | new StdXMLBuilder()); 80 | } 81 | 82 | 83 | /** 84 | * Creates a default parser. 85 | * 86 | * @see #DEFAULT_CLASS 87 | * @see #CLASS_KEY 88 | * 89 | * @param builder the XML builder. 90 | * 91 | * @return the non-null parser. 92 | * 93 | * @throws java.lang.ClassNotFoundException 94 | * if the class of the parser could not be found. 95 | * @throws java.lang.InstantiationException 96 | * if the parser could not be created 97 | * @throws java.lang.IllegalAccessException 98 | * if the parser could not be created 99 | */ 100 | public static IXMLParser createDefaultXMLParser(IXMLBuilder builder) 101 | throws ClassNotFoundException, 102 | InstantiationException, 103 | IllegalAccessException 104 | { 105 | String className = System.getProperty(XMLParserFactory.CLASS_KEY, 106 | XMLParserFactory.DEFAULT_CLASS); 107 | return XMLParserFactory.createXMLParser(className, builder); 108 | } 109 | 110 | 111 | /** 112 | * Creates a parser. 113 | * 114 | * @param className the name of the class of the XML parser 115 | * @param builder the XML builder. 116 | * 117 | * @return the non-null parser. 118 | * 119 | * @throws java.lang.ClassNotFoundException 120 | * if the class of the parser could not be found. 121 | * @throws java.lang.InstantiationException 122 | * if the parser could not be created 123 | * @throws java.lang.IllegalAccessException 124 | * if the parser could not be created 125 | */ 126 | public static IXMLParser createXMLParser(String className, 127 | IXMLBuilder builder) 128 | throws ClassNotFoundException, 129 | InstantiationException, 130 | IllegalAccessException 131 | { 132 | Class cls = Class.forName(className); 133 | IXMLParser parser = (IXMLParser) cls.newInstance(); 134 | parser.setBuilder(builder); 135 | parser.setValidator(new NonValidator()); 136 | return parser; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLValidationException.java: -------------------------------------------------------------------------------- 1 | /* XMLValidationException.java NanoXML/Java 2 | * 3 | * $Revision: 1.3 $ 4 | * $Date: 2002/01/04 21:03:29 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | /** 33 | * @author kriesen 34 | */ 35 | public class XMLValidationException 36 | extends XMLException 37 | { 38 | 39 | /** 40 | * An element was missing. 41 | */ 42 | public static final int MISSING_ELEMENT = 1; 43 | 44 | 45 | /** 46 | * An unexpected element was encountered. 47 | */ 48 | public static final int UNEXPECTED_ELEMENT = 2; 49 | 50 | 51 | /** 52 | * An attribute was missing. 53 | */ 54 | public static final int MISSING_ATTRIBUTE = 3; 55 | 56 | 57 | /** 58 | * An unexpected attribute was encountered. 59 | */ 60 | public static final int UNEXPECTED_ATTRIBUTE = 4; 61 | 62 | 63 | /** 64 | * An attribute has an invalid value. 65 | */ 66 | public static final int ATTRIBUTE_WITH_INVALID_VALUE = 5; 67 | 68 | 69 | /** 70 | * A PCDATA element was missing. 71 | */ 72 | public static final int MISSING_PCDATA = 6; 73 | 74 | 75 | /** 76 | * An unexpected PCDATA element was encountered. 77 | */ 78 | public static final int UNEXPECTED_PCDATA = 7; 79 | 80 | 81 | /** 82 | * Another error than those specified in this class was encountered. 83 | */ 84 | public static final int MISC_ERROR = 0; 85 | 86 | 87 | /** 88 | * Which error occurred. 89 | */ 90 | private int errorType; 91 | 92 | 93 | /** 94 | * The name of the element where the exception occurred. 95 | */ 96 | private String elementName; 97 | 98 | 99 | /** 100 | * The name of the attribute where the exception occurred. 101 | */ 102 | private String attributeName; 103 | 104 | 105 | /** 106 | * The value of the attribute where the exception occurred. 107 | */ 108 | private String attributeValue; 109 | 110 | 111 | /** 112 | * Creates a new exception. 113 | * 114 | * @param errorType the type of validity error 115 | * @param systemID the system ID from where the data came 116 | * @param lineNr the line number in the XML data where the 117 | * exception occurred. 118 | * @param elementName the name of the offending element 119 | * @param attributeName the name of the offending attribute 120 | * @param attributeValue the value of the offending attribute 121 | * @param msg the message of the exception. 122 | */ 123 | public XMLValidationException(int errorType, 124 | String systemID, 125 | int lineNr, 126 | String elementName, 127 | String attributeName, 128 | String attributeValue, 129 | String msg) 130 | { 131 | super(systemID, lineNr, null, 132 | msg + ((elementName == null) ? "" : (", element=" + elementName)) 133 | + ((attributeName == null) ? "" 134 | : (", attribute=" + attributeName)) 135 | + ((attributeValue == null) ? "" 136 | : (", value='" + attributeValue + "'")), 137 | false); 138 | this.elementName = elementName; 139 | this.attributeName = attributeName; 140 | this.attributeValue = attributeValue; 141 | } 142 | 143 | 144 | /** 145 | * Cleans up the object when it's destroyed. 146 | */ 147 | protected void finalize() 148 | throws Throwable 149 | { 150 | this.elementName = null; 151 | this.attributeName = null; 152 | this.attributeValue = null; 153 | super.finalize(); 154 | } 155 | 156 | 157 | /** 158 | * Returns the name of the element in which the validation is violated. If there is no current element, null is returned. 159 | * @uml.property name="elementName" 160 | */ 161 | public String getElementName() 162 | { 163 | return this.elementName; 164 | } 165 | 166 | 167 | /** 168 | * Returns the name of the attribute in which the validation is violated. If there is no current attribute, null is returned. 169 | * @uml.property name="attributeName" 170 | */ 171 | public String getAttributeName() 172 | { 173 | return this.attributeName; 174 | } 175 | 176 | 177 | /** 178 | * Returns the value of the attribute in which the validation is violated. If there is no current attribute, null is returned. 179 | * @uml.property name="attributeValue" 180 | */ 181 | public String getAttributeValue() 182 | { 183 | return this.attributeValue; 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/XMLWriter.java: -------------------------------------------------------------------------------- 1 | /* XMLWriter.java NanoXML/Java 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/03/24 11:37:51 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml; 30 | 31 | 32 | import java.io.IOException; 33 | import java.io.OutputStream; 34 | import java.io.PrintWriter; 35 | import java.io.Writer; 36 | import java.util.Enumeration; 37 | import java.util.Vector; 38 | 39 | 40 | /** 41 | * An XMLWriter writes XML data to a stream. 42 | * 43 | * @see net.n3.nanoxml.IXMLElement 44 | * @see java.io.Writer 45 | * 46 | * @author Marc De Scheemaecker 47 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $ 48 | */ 49 | public class XMLWriter 50 | { 51 | 52 | /** 53 | * Where to write the output to. 54 | */ 55 | private PrintWriter writer; 56 | 57 | 58 | /** 59 | * Creates a new XML writer. 60 | * 61 | * @param writer where to write the output to. 62 | */ 63 | public XMLWriter(Writer writer) 64 | { 65 | if (writer instanceof PrintWriter) { 66 | this.writer = (PrintWriter) writer; 67 | } else { 68 | this.writer = new PrintWriter(writer); 69 | } 70 | } 71 | 72 | 73 | /** 74 | * Creates a new XML writer. 75 | * 76 | * @param stream where to write the output to. 77 | */ 78 | public XMLWriter(OutputStream stream) 79 | { 80 | this.writer = new PrintWriter(stream); 81 | } 82 | 83 | 84 | /** 85 | * Cleans up the object when it's destroyed. 86 | */ 87 | protected void finalize() 88 | throws Throwable 89 | { 90 | this.writer = null; 91 | super.finalize(); 92 | } 93 | 94 | 95 | /** 96 | * Writes an XML element. 97 | * 98 | * @param xml the non-null XML element to write. 99 | */ 100 | public void write(IXMLElement xml) 101 | throws IOException 102 | { 103 | this.write(xml, false, 0, true); 104 | } 105 | 106 | 107 | /** 108 | * Writes an XML element. 109 | * 110 | * @param xml the non-null XML element to write. 111 | * @param prettyPrint if spaces need to be inserted to make the output more 112 | * readable 113 | */ 114 | public void write(IXMLElement xml, 115 | boolean prettyPrint) 116 | throws IOException 117 | { 118 | this.write(xml, prettyPrint, 0, true); 119 | } 120 | 121 | 122 | /** 123 | * Writes an XML element. 124 | * 125 | * @param xml the non-null XML element to write. 126 | * @param prettyPrint if spaces need to be inserted to make the output more 127 | * readable 128 | * @param indent how many spaces to indent the element. 129 | */ 130 | public void write(IXMLElement xml, 131 | boolean prettyPrint, 132 | int indent) 133 | throws IOException 134 | { 135 | this.write(xml, prettyPrint, indent, true); 136 | } 137 | 138 | 139 | /** 140 | * Writes an XML element. 141 | * 142 | * @param xml the non-null XML element to write. 143 | * @param prettyPrint if spaces need to be inserted to make the output more 144 | * readable 145 | * @param indent how many spaces to indent the element. 146 | */ 147 | public void write(IXMLElement xml, 148 | boolean prettyPrint, 149 | int indent, 150 | boolean collapseEmptyElements) 151 | throws IOException 152 | { 153 | if (prettyPrint) { 154 | for (int i = 0; i < indent; i++) { 155 | this.writer.print(' '); 156 | } 157 | } 158 | 159 | if (xml.getName() == null) { 160 | if (xml.getContent() != null) { 161 | if (prettyPrint) { 162 | this.writeEncoded(xml.getContent().trim()); 163 | writer.println(); 164 | } else { 165 | this.writeEncoded(xml.getContent()); 166 | } 167 | } 168 | } else { 169 | this.writer.print('<'); 170 | this.writer.print(xml.getFullName()); 171 | Vector nsprefixes = new Vector(); 172 | 173 | if (xml.getNamespace() != null) { 174 | if (xml.getName().equals(xml.getFullName())) { 175 | this.writer.print(" xmlns=\"" + xml.getNamespace() + '"'); 176 | } else { 177 | String prefix = xml.getFullName(); 178 | prefix = prefix.substring(0, prefix.indexOf(':')); 179 | nsprefixes.addElement(prefix); 180 | this.writer.print(" xmlns:" + prefix); 181 | this.writer.print("=\"" + xml.getNamespace() + "\""); 182 | } 183 | } 184 | 185 | Enumeration enume = xml.enumerateAttributeNames(); 186 | 187 | while (enume.hasMoreElements()) { 188 | String key = (String) enume.nextElement(); 189 | int index = key.indexOf(':'); 190 | 191 | if (index >= 0) { 192 | String namespace = xml.getAttributeNamespace(key); 193 | 194 | if (namespace != null) { 195 | String prefix = key.substring(0, index); 196 | 197 | if (! nsprefixes.contains(prefix)) { 198 | this.writer.print(" xmlns:" + prefix); 199 | this.writer.print("=\"" + namespace + '"'); 200 | nsprefixes.addElement(prefix); 201 | } 202 | } 203 | } 204 | } 205 | 206 | enume = xml.enumerateAttributeNames(); 207 | 208 | while (enume.hasMoreElements()) { 209 | String key = (String) enume.nextElement(); 210 | String value = xml.getAttribute(key, null); 211 | this.writer.print(" " + key + "=\""); 212 | this.writeEncoded(value); 213 | this.writer.print('"'); 214 | } 215 | 216 | if ((xml.getContent() != null) 217 | && (xml.getContent().length() > 0)) { 218 | writer.print('>'); 219 | this.writeEncoded(xml.getContent()); 220 | writer.print("'); 221 | 222 | if (prettyPrint) { 223 | writer.println(); 224 | } 225 | } else if (xml.hasChildren() || (! collapseEmptyElements)) { 226 | writer.print('>'); 227 | 228 | if (prettyPrint) { 229 | writer.println(); 230 | } 231 | 232 | enume = xml.enumerateChildren(); 233 | 234 | while (enume.hasMoreElements()) { 235 | IXMLElement child = (IXMLElement) enume.nextElement(); 236 | this.write(child, prettyPrint, indent + 4, 237 | collapseEmptyElements); 238 | } 239 | 240 | if (prettyPrint) { 241 | for (int i = 0; i < indent; i++) { 242 | this.writer.print(' '); 243 | } 244 | } 245 | 246 | this.writer.print(""); 247 | 248 | if (prettyPrint) { 249 | writer.println(); 250 | } 251 | } else { 252 | this.writer.print("/>"); 253 | 254 | if (prettyPrint) { 255 | writer.println(); 256 | } 257 | } 258 | } 259 | 260 | this.writer.flush(); 261 | } 262 | 263 | 264 | /** 265 | * Writes a string encoding reserved characters. 266 | * 267 | * @param str the string to write. 268 | */ 269 | private void writeEncoded(String str) 270 | { 271 | for (int i = 0; i < str.length(); i++) { 272 | char c = str.charAt(i); 273 | 274 | switch (c) { 275 | case 0x0A: 276 | this.writer.print(c); 277 | break; 278 | 279 | case '<': 280 | this.writer.print("<"); 281 | break; 282 | 283 | case '>': 284 | this.writer.print(">"); 285 | break; 286 | 287 | case '&': 288 | this.writer.print("&"); 289 | break; 290 | 291 | case '\'': 292 | this.writer.print("'"); 293 | break; 294 | 295 | case '"': 296 | this.writer.print("""); 297 | break; 298 | 299 | default: 300 | if ((c < ' ') || (c > 0x7E)) { 301 | this.writer.print("&#x"); 302 | this.writer.print(Integer.toString(c, 16)); 303 | this.writer.print(';'); 304 | } else { 305 | this.writer.print(c); 306 | } 307 | } 308 | } 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/sax/SAXEntityResolver.java: -------------------------------------------------------------------------------- 1 | /* SAXEntityResolver.java NanoXML/SAX 2 | * 3 | * $Revision: 1.4 $ 4 | * $Date: 2002/01/04 21:03:28 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of the SAX adapter for NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml.sax; 30 | 31 | 32 | import java.io.InputStream; 33 | import java.io.InputStreamReader; 34 | import java.io.Reader; 35 | import java.net.URL; 36 | import net.n3.nanoxml.XMLEntityResolver; 37 | import net.n3.nanoxml.IXMLReader; 38 | import org.xml.sax.EntityResolver; 39 | import org.xml.sax.InputSource; 40 | 41 | 42 | /** 43 | * SAXEntityResolver is a subclass of XMLEntityResolver that supports the 44 | * SAX EntityResolver listener. 45 | * 46 | * @see net.n3.nanoxml.IXMLEntityResolver 47 | * 48 | * @author Marc De Scheemaecker 49 | * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $ 50 | */ 51 | public class SAXEntityResolver 52 | extends XMLEntityResolver 53 | { 54 | 55 | /** 56 | * The SAX EntityResolver listener. 57 | */ 58 | private EntityResolver saxEntityResolver; 59 | 60 | 61 | /** 62 | * Creates the resolver. 63 | */ 64 | public SAXEntityResolver() 65 | { 66 | this.saxEntityResolver = null; 67 | } 68 | 69 | 70 | /** 71 | * Cleans up the object when it's destroyed. 72 | */ 73 | protected void finalize() 74 | throws Throwable 75 | { 76 | this.saxEntityResolver = null; 77 | super.finalize(); 78 | } 79 | 80 | 81 | /** 82 | * Sets the SAX EntityResolver listener. 83 | * 84 | * @param resolver the entity resolver 85 | */ 86 | public void setEntityResolver(EntityResolver resolver) 87 | { 88 | this.saxEntityResolver = resolver; 89 | } 90 | 91 | 92 | /** 93 | * Opens an external entity. 94 | * 95 | * @param xmlReader the current XML reader 96 | * @param publicID the public ID, which may be null 97 | * @param systemID the system ID 98 | * 99 | * @return the reader, or null if the reader could not be created/opened 100 | */ 101 | protected Reader openExternalEntity(IXMLReader xmlReader, 102 | String publicID, 103 | String systemID) 104 | { 105 | try { 106 | URL url = new URL(xmlReader.getSystemID()); 107 | url = new URL(url, systemID); 108 | 109 | if (this.saxEntityResolver != null) { 110 | InputSource source 111 | = this.saxEntityResolver 112 | .resolveEntity(publicID, url.toString()); 113 | 114 | if (source != null) { 115 | Reader reader = source.getCharacterStream(); 116 | 117 | if (reader != null) { 118 | return reader; 119 | } 120 | 121 | InputStream stream = source.getByteStream(); 122 | 123 | if (stream == null) { 124 | publicID = source.getPublicId(); 125 | systemID = source.getSystemId(); 126 | } else { 127 | String encoding = source.getEncoding(); 128 | 129 | if (encoding != null) { 130 | return new InputStreamReader(stream, encoding); 131 | } else { // if encoding == null 132 | return new InputStreamReader(stream); 133 | } 134 | } 135 | } 136 | } 137 | 138 | return super.openExternalEntity(xmlReader, publicID, systemID); 139 | } catch (Exception e) { 140 | return null; 141 | } 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/net/n3/nanoxml/sax/SAXParser.java: -------------------------------------------------------------------------------- 1 | /* SAXParser.java NanoXML/SAX 2 | * 3 | * $Revision: 1.5 $ 4 | * $Date: 2002/03/24 11:39:20 $ 5 | * $Name: RELEASE_2_2_1 $ 6 | * 7 | * This file is part of the SAX adapter for NanoXML 2 for Java. 8 | * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. 9 | * 10 | * This software is provided 'as-is', without any express or implied warranty. 11 | * In no event will the authors be held liable for any damages arising from the 12 | * use of this software. 13 | * 14 | * Permission is granted to anyone to use this software for any purpose, 15 | * including commercial applications, and to alter it and redistribute it 16 | * freely, subject to the following restrictions: 17 | * 18 | * 1. The origin of this software must not be misrepresented; you must not 19 | * claim that you wrote the original software. If you use this software in 20 | * a product, an acknowledgment in the product documentation would be 21 | * appreciated but is not required. 22 | * 23 | * 2. Altered source versions must be plainly marked as such, and must not be 24 | * misrepresented as being the original software. 25 | * 26 | * 3. This notice may not be removed or altered from any source distribution. 27 | */ 28 | 29 | package net.n3.nanoxml.sax; 30 | 31 | 32 | import java.io.FileNotFoundException; 33 | import java.io.InputStream; 34 | import java.io.InputStreamReader; 35 | import java.io.IOException; 36 | import java.io.Reader; 37 | import java.io.UnsupportedEncodingException; 38 | import java.net.MalformedURLException; 39 | import java.util.Locale; 40 | import net.n3.nanoxml.IXMLBuilder; 41 | import net.n3.nanoxml.IXMLParser; 42 | import net.n3.nanoxml.IXMLReader; 43 | import net.n3.nanoxml.StdXMLReader; 44 | import net.n3.nanoxml.XMLParserFactory; 45 | import org.xml.sax.Parser; 46 | import org.xml.sax.DocumentHandler; 47 | import org.xml.sax.DTDHandler; 48 | import org.xml.sax.EntityResolver; 49 | import org.xml.sax.ErrorHandler; 50 | import org.xml.sax.HandlerBase; 51 | import org.xml.sax.InputSource; 52 | import org.xml.sax.Locator; 53 | import org.xml.sax.SAXException; 54 | import org.xml.sax.helpers.AttributeListImpl; 55 | import org.xml.sax.helpers.LocatorImpl; 56 | 57 | 58 | /** 59 | * @author kriesen 60 | */ 61 | public class SAXParser 62 | implements Parser 63 | { 64 | 65 | /** 66 | * The SAX adapter. 67 | */ 68 | private SAXAdapter adapter; 69 | 70 | 71 | /** 72 | * The client error handler. 73 | */ 74 | private ErrorHandler errorHandler; 75 | 76 | 77 | /** 78 | * The entity resolver. 79 | */ 80 | private SAXEntityResolver entityResolver; 81 | 82 | 83 | /** 84 | * Creates the SAX parser. 85 | */ 86 | public SAXParser() 87 | { 88 | this.adapter = new SAXAdapter(); 89 | this.errorHandler = new HandlerBase(); 90 | this.entityResolver = new SAXEntityResolver(); 91 | } 92 | 93 | 94 | /** 95 | * Cleans up the object when it's destroyed. 96 | */ 97 | protected void finalize() 98 | throws Throwable 99 | { 100 | this.adapter = null; 101 | this.errorHandler = null; 102 | this.entityResolver = null; 103 | super.finalize(); 104 | } 105 | 106 | 107 | /** 108 | * Sets the locale. Only locales using the language english are accepted. 109 | * 110 | * @param locale the locale 111 | * 112 | * @exception org.xml.sax.SAXException 113 | * if locale is null or the associated 114 | * language is not english. 115 | */ 116 | public void setLocale(Locale locale) 117 | throws SAXException 118 | { 119 | if ((locale == null) || (! locale.getLanguage().equals("en"))) { 120 | throw new SAXException("NanoXML/SAX doesn't support locale: " 121 | + locale); 122 | } 123 | } 124 | 125 | 126 | /** 127 | * Sets the entity resolver. 128 | * 129 | * @param resolver the entity resolver 130 | */ 131 | public void setEntityResolver(EntityResolver resolver) 132 | { 133 | this.entityResolver.setEntityResolver(resolver); 134 | } 135 | 136 | 137 | /** 138 | * Sets the DTD handler. As the parser is non-validating, this handler is 139 | * never called. 140 | * 141 | * @param handler the DTD handler 142 | */ 143 | public void setDTDHandler(DTDHandler handler) 144 | { 145 | // nothing to do 146 | } 147 | 148 | 149 | /** 150 | * Allows an application to register a document event handler. 151 | * 152 | * @param handler the document handler 153 | */ 154 | public void setDocumentHandler(DocumentHandler handler) 155 | { 156 | this.adapter.setDocumentHandler(handler); 157 | } 158 | 159 | 160 | /** 161 | * Allow an application to register an error event handler. 162 | * @param handler the error handler 163 | * @uml.property name="errorHandler" 164 | */ 165 | public void setErrorHandler(ErrorHandler handler) 166 | { 167 | this.errorHandler = handler; 168 | } 169 | 170 | 171 | /** 172 | * Creates the XML parser. 173 | */ 174 | private IXMLParser createParser() 175 | throws SAXException 176 | { 177 | try { 178 | return XMLParserFactory.createDefaultXMLParser(); 179 | } catch (Exception exception) { 180 | throw new SAXException(exception); 181 | } 182 | } 183 | 184 | 185 | /** 186 | * Parse an XML document. 187 | * 188 | * @param source the input source 189 | */ 190 | public void parse(InputSource source) 191 | throws SAXException, 192 | IOException 193 | { 194 | IXMLParser parser = this.createParser(); 195 | parser.setBuilder(this.adapter); 196 | parser.setResolver(this.entityResolver); 197 | Reader reader = source.getCharacterStream(); 198 | 199 | if (reader != null) { 200 | parser.setReader(new StdXMLReader(reader)); 201 | } else { 202 | InputStream stream = source.getByteStream(); 203 | 204 | if (stream != null) { 205 | String encoding = source.getEncoding(); 206 | 207 | if (encoding != null) { 208 | try { 209 | reader = new InputStreamReader(stream, encoding); 210 | parser.setReader(new StdXMLReader(reader)); 211 | } catch (UnsupportedEncodingException exception) { 212 | throw new SAXException(exception); 213 | } 214 | } else { // if encoding == null 215 | parser.setReader(new StdXMLReader(stream)); 216 | } 217 | } else { // if stream == null 218 | parser.setReader(new StdXMLReader(source.getPublicId(), 219 | source.getSystemId())); 220 | } 221 | } 222 | 223 | try { 224 | parser.parse(); 225 | this.adapter.endDocument(); 226 | } catch (IOException exception) { 227 | throw exception; 228 | } catch (Exception exception) { 229 | throw new SAXException(exception); 230 | } finally { 231 | reader.close(); 232 | } 233 | } 234 | 235 | 236 | /** 237 | * Parse an XML document from a system identifier (URI). 238 | * 239 | * @param systemId the system ID 240 | */ 241 | public void parse(String systemId) 242 | throws SAXException, 243 | IOException 244 | { 245 | IXMLParser parser = this.createParser(); 246 | parser.setBuilder(this.adapter); 247 | parser.setReader(new StdXMLReader(null, systemId)); 248 | 249 | try { 250 | parser.parse(); 251 | this.adapter.endDocument(); 252 | } catch (IOException exception) { 253 | throw exception; 254 | } catch (Exception exception) { 255 | throw new SAXException(exception); 256 | } 257 | } 258 | 259 | } 260 | -------------------------------------------------------------------------------- /src/util/AssignmentAndCost.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class AssignmentAndCost implements Comparable { 4 | 5 | private double cost; 6 | 7 | private int from, to; 8 | 9 | public int getFrom() { 10 | return from; 11 | } 12 | 13 | public int getTo() { 14 | return to; 15 | } 16 | 17 | public AssignmentAndCost(int f, int t, double cost) { 18 | this.from = f; 19 | this.to = t; 20 | this.cost = cost; 21 | } 22 | 23 | @Override 24 | public int compareTo(AssignmentAndCost other) { 25 | if (this.cost == other.cost){ 26 | return 0; 27 | } 28 | if (this.cost > other.cost){ 29 | return 1; 30 | } else { 31 | return -1; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/util/Bunke.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Collections; 4 | import java.util.LinkedList; 5 | 6 | import algorithms.BipartiteMatching; 7 | 8 | public class Bunke { 9 | 10 | private Graph sourceGraph; 11 | private Graph targetGraph; 12 | private int[][] matching; 13 | private CostFunction costFunction; 14 | private EditDistance editDistance; 15 | private double[][] costMatrix; 16 | private BipartiteMatching bipartiteMatching; 17 | private MatrixGenerator matrixGenerator; 18 | private int[][] firstPartOfMatching; 19 | private int[][] secondPartOfMatching; 20 | 21 | public Bunke(Graph s, Graph t, int[][] m, CostFunction cf, EditDistance ed, double[][] cm, BipartiteMatching bm, MatrixGenerator mg) { 22 | this.sourceGraph = s; 23 | this.targetGraph = t; 24 | this.matching = m; 25 | this.costFunction = cf; 26 | this.editDistance = ed; 27 | this.costMatrix = cm; 28 | this.bipartiteMatching = bm; 29 | this.matrixGenerator = mg; 30 | } 31 | 32 | public double getBetterMatching(double percentage) { 33 | 34 | LinkedList macList = new LinkedList(); 35 | for (int i = 0; i < this.matching.length;i++){ 36 | int from = this.matching[i][0]; 37 | int to = this.matching[i][1]; 38 | MatchingAndCost mac = new MatchingAndCost(from, to, this.costMatrix[from][to]); 39 | macList.add(mac); 40 | } 41 | Collections.sort(macList); 42 | int f = (int) (macList.size() * percentage); 43 | this.firstPartOfMatching = new int[f][2]; 44 | for (int i = 0; i < f; i++){ 45 | MatchingAndCost mac = macList.removeFirst(); 46 | int from = mac.getFrom();; 47 | int to = mac.getTo(); 48 | this.firstPartOfMatching[i][0] = from; 49 | this.firstPartOfMatching[i][1] = to; 50 | } 51 | // debugging vvvvvvvvvvvvvvv 52 | System.out.println("The first part of the matching:"); 53 | for (int i = 0; i < this.firstPartOfMatching.length; i++){ 54 | System.out.println(this.firstPartOfMatching[i][0]+" --> "+this.firstPartOfMatching[i][1]); 55 | } 56 | // debugging ^^^^^^^^^^^^^^^ 57 | 58 | // this.costMatrix = this.matrixGenerator.getMatrix(sourceGraph, targetGraph, this.firstPartOfMatching); 59 | // this.secondPartOfMatching = this.bipartiteMatching.getMatching(costMatrix); 60 | // calculate the approximated edit-distance according to the bipartite matching 61 | // TODO --> merge matchings!!! 62 | double d = this.editDistance.getEditDistance(sourceGraph, 63 | targetGraph, matching, costFunction); 64 | return d; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/util/CentralityInterface.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | 4 | import edu.uci.ics.jung.graph.SparseMultigraph; 5 | import edu.uci.ics.jung.graph.util.EdgeType; 6 | import edu.uci.ics.jung.algorithms.scoring.*; 7 | import edu.uci.ics.jung.algorithms.shortestpath.*; 8 | 9 | /** 10 | * This class encapsulates the CentraliyMeasure classes of the JUNG graph 11 | * algorithm library. 12 | * 13 | */ 14 | public class CentralityInterface { 15 | 16 | 17 | 18 | /** 19 | * Calculates the specified centrality rank score for all nodes of a given 20 | * graph and sets the score in the node class. 21 | * 22 | * @param graph 23 | */ 24 | public static void rankNodes(Graph graph, String cMeasure){ 25 | // set up graph 26 | EdgeType edgeType = graph.isDirected() ? EdgeType.DIRECTED : EdgeType.UNDIRECTED; 27 | SparseMultigraph jungGraph = new SparseMultigraph(); 28 | for (Node node : graph) { 29 | jungGraph.addVertex(node); 30 | } 31 | 32 | Edge[][] adjacenyMatrix = graph.getAdjacenyMatrix(); 33 | for (int i = 0; i < adjacenyMatrix.length; i++) { 34 | Edge[] edges = adjacenyMatrix[i]; 35 | for (int j = 0; j < edges.length; j++) { 36 | Edge edge = edges[j]; 37 | if (edge != null){ 38 | jungGraph.addEdge(edge, edge.getStartNode(), edge.getEndNode(), edgeType); 39 | } 40 | } 41 | } 42 | if (cMeasure.equals("Barycenter")){ 43 | BarycenterScorer centrality = new BarycenterScorer(jungGraph); 44 | for (Node node : graph) { 45 | double score = (Double) centrality.getVertexScore(node); 46 | node.setCentrality(score); 47 | } 48 | return; 49 | } 50 | if (cMeasure.equals("Betweenness")){ 51 | BetweennessCentrality centrality = new BetweennessCentrality(jungGraph); 52 | for (Node node : graph) { 53 | double score = (Double) centrality.getVertexScore(node); 54 | node.setCentrality(score); 55 | } 56 | return; 57 | } 58 | if (cMeasure.equals("Closeness")){ 59 | ClosenessCentrality centrality = new ClosenessCentrality(jungGraph); 60 | for (Node node : graph) { 61 | double score = (Double) centrality.getVertexScore(node); 62 | node.setCentrality(score); 63 | } 64 | return; 65 | } 66 | if (cMeasure.equals("Degree")){ 67 | DegreeScorer centrality = new DegreeScorer(jungGraph); 68 | for (Node node : graph) { 69 | double score = (Integer) centrality.getVertexScore(node); 70 | node.setCentrality(score); 71 | } 72 | return; 73 | } 74 | if (cMeasure.equals("Eigenvector")){ 75 | EigenvectorCentrality centrality = new EigenvectorCentrality(jungGraph); 76 | for (Node node : graph) { 77 | double score = (Double) centrality.getVertexScore(node); 78 | node.setCentrality(score); 79 | } 80 | return; 81 | } 82 | if (cMeasure.equals("HITS")){ 83 | HITS hits = new HITS(jungGraph); 84 | hits.evaluate(); 85 | for (Node node : graph) { 86 | HITS.Scores score = hits.getVertexScore(node); 87 | node.setCentrality(score.hub); 88 | node.setCentrality(score.authority); 89 | } 90 | } 91 | if (cMeasure.equals("Pagerank")){ 92 | PageRank pageRankCentrality = new PageRank(jungGraph, 0.1); 93 | pageRankCentrality.evaluate(); 94 | for (Node node : graph) { 95 | double score = (Double) pageRankCentrality.getVertexScore(node); 96 | node.setCentrality(score); 97 | } 98 | return; 99 | } 100 | System.out.println("ERROR NO VALID CENTRALITY MEASURE..."); 101 | System.exit(0); 102 | 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/util/DoubleIndex.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class DoubleIndex { 4 | 5 | private int from; 6 | 7 | public int getFrom() { 8 | return from; 9 | } 10 | 11 | public void setFrom(int from) { 12 | this.from = from; 13 | } 14 | 15 | public int getTo() { 16 | return to; 17 | } 18 | 19 | public void setTo(int to) { 20 | this.to = to; 21 | } 22 | 23 | private int to; 24 | 25 | public DoubleIndex(int from, int to) { 26 | this.from = from; 27 | this.to = to; 28 | } 29 | 30 | public String toString(){ 31 | return "("+this.from+", "+this.to+")"; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/util/Edge.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Hashtable; 4 | 5 | public class Edge { 6 | 7 | /** the identifier of the edge */ 8 | private String edgeID; 9 | 10 | /** the attributes of the edge*/ 11 | private Hashtable attributes; 12 | 13 | /** the start and end node of the edge*/ 14 | private Node startNode; 15 | private Node endNode; 16 | 17 | 18 | 19 | /** 20 | * Constructors 21 | */ 22 | public Edge() { 23 | this.attributes = new Hashtable(); 24 | } 25 | public Edge(String id) { 26 | this.edgeID = id; 27 | } 28 | 29 | /** 30 | * gets the other end of the edge 31 | */ 32 | public Node getOtherEnd(Node n) { 33 | if (n.equals(this.startNode)){ 34 | return this.endNode; 35 | } else { 36 | return this.startNode; 37 | } 38 | 39 | } 40 | 41 | /** 42 | * puts a new attribute 43 | * in the attribute-table 44 | */ 45 | public void put(String key, String value){ 46 | this.attributes.put(key, value); 47 | } 48 | 49 | /** 50 | * @return the attribute-value of 51 | * @param key 52 | */ 53 | public String getValue(String key){ 54 | return this.attributes.get(key); 55 | } 56 | 57 | 58 | /** 59 | * generates a printable string of the edge 60 | */ 61 | public String toString(){ 62 | String edge = this.edgeID+" "; 63 | edge += this.attributes; 64 | return edge; 65 | } 66 | 67 | 68 | 69 | /** 70 | * some getters and setters 71 | */ 72 | 73 | public String getEdgeID() { 74 | return edgeID; 75 | } 76 | 77 | public void setEdgeID(String edgeID) { 78 | this.edgeID = edgeID; 79 | } 80 | 81 | public Node getStartNode() { 82 | return startNode; 83 | } 84 | 85 | public void setStartNode(Node startNode) { 86 | this.startNode = startNode; 87 | } 88 | 89 | public Node getEndNode() { 90 | return endNode; 91 | } 92 | 93 | public void setEndNode(Node endNode) { 94 | this.endNode = endNode; 95 | } 96 | 97 | 98 | 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/util/FloatingSearch.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzambon/graph-matching-toolkit/8b3ab3cef2453d52d182af24a28452359eedfedc/src/util/FloatingSearch.java -------------------------------------------------------------------------------- /src/util/FloatingSearch2.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | 6 | import algorithms.BipartiteMatching; 7 | 8 | public class FloatingSearch2 { 9 | 10 | private Graph sourceGraph; 11 | private Graph targetGraph; 12 | private int[][] originalMatching; 13 | private CostFunction costFunction; 14 | private EditDistance editDistance; 15 | private double[][] originalCostMatrix; 16 | private BipartiteMatching bipartiteMatching; 17 | 18 | public FloatingSearch2(Graph sourceGraph, Graph targetGraph, 19 | int[][] matching, CostFunction costFunction, 20 | EditDistance editDistance, double[][] costMatrix, 21 | BipartiteMatching bipartiteMatching) { 22 | this.sourceGraph = sourceGraph; 23 | this.targetGraph = targetGraph; 24 | this.originalMatching = matching; 25 | this.costFunction = costFunction; 26 | this.editDistance = editDistance; 27 | this.originalCostMatrix = costMatrix; 28 | this.bipartiteMatching = bipartiteMatching; 29 | } 30 | 31 | public double searchBetter() { 32 | double[] distances = new double[this.originalMatching.length+1]; 33 | Arrays.fill(distances, Double.MAX_VALUE); 34 | 35 | double d = this.editDistance.getEditDistance(this.sourceGraph, 36 | this.targetGraph, this.originalMatching, this.costFunction); 37 | distances[0] = d; 38 | 39 | int[][] m = this.originalMatching; 40 | double[][] cm = this.copyMatrix(this.originalCostMatrix); 41 | 42 | LinkedList forbiddenIndices = new LinkedList(); 43 | 44 | 45 | for (int i = 0; i < this.originalMatching.length; i++){ 46 | // System.out.println("*** "+i+" Forbidden are: "+forbiddenIndices); 47 | // this.printDistances(distances); 48 | m = this.bipartiteMatching.getMatching(cm); 49 | this.editDistance.getEditDistance(this.sourceGraph, 50 | this.targetGraph, m, this.costFunction); 51 | int forbid = this.computeForbid(m, cm); 52 | if (forbid > -1) { 53 | forbiddenIndices.add(new DoubleIndex(forbid, m[forbid][1])); 54 | cm[forbid][m[forbid][1]] = Double.MAX_VALUE; 55 | 56 | m = this.bipartiteMatching.getMatching(cm); 57 | 58 | double distance = this.editDistance.getEditDistance(sourceGraph, 59 | targetGraph, m, costFunction); 60 | distances[i+1] = distance; 61 | 62 | boolean improved = true; 63 | int j = -1; 64 | while (improved){ 65 | j++; 66 | improved = false; 67 | int bestRemove = -1; 68 | for (int k = 0; k < forbiddenIndices.size(); k++){ 69 | int f = forbiddenIndices.get(k).getFrom(); 70 | int t = forbiddenIndices.get(k).getTo(); 71 | cm[f][t] = this.originalCostMatrix[f][t]; 72 | m = this.bipartiteMatching.getMatching(cm); 73 | distance = this.editDistance.getEditDistance(sourceGraph, 74 | targetGraph, m, costFunction); 75 | if (distance < distances[i-j]){ 76 | distances[i-j] = distance; 77 | bestRemove = k; 78 | improved = true; 79 | } else { 80 | } 81 | cm[f][t] = Double.MAX_VALUE; 82 | } 83 | if (bestRemove != -1){ 84 | 85 | DoubleIndex removed = forbiddenIndices.remove(bestRemove); 86 | cm[removed.getFrom()][removed.getTo()] = this.originalCostMatrix[removed.getFrom()][removed.getTo()]; 87 | } 88 | } 89 | i = i-j; 90 | } else { 91 | i = this.originalMatching.length; 92 | } 93 | } 94 | return this.getMinimum(distances); 95 | } 96 | 97 | private int computeForbid(int[][] m, double[][] cm) { 98 | double minDist = Double.MAX_VALUE; 99 | int minIndex = -1; 100 | for (int i = 0; i < m.length; i++){ 101 | int f = m[i][0]; 102 | int t = m[i][1]; 103 | double temp = cm[f][t]; 104 | cm[f][t] = Double.MAX_VALUE; 105 | m = this.bipartiteMatching.getMatching(cm); 106 | double d = this.editDistance.getEditDistance(this.sourceGraph, 107 | this.targetGraph, m, this.costFunction); 108 | if (d < minDist){ 109 | minDist = d; 110 | minIndex = i; 111 | } 112 | cm[f][t] = temp; 113 | } 114 | return minIndex; 115 | } 116 | 117 | private void printDistances(double[] distances) { 118 | for (int i = 0; i < distances.length; i++){ 119 | System.out.println("d["+i+"] = "+distances[i]); 120 | } 121 | 122 | } 123 | 124 | private void printMatching(int[][] m) { 125 | for (int i = 0; i < m.length; i++){ 126 | System.out.print(m[i][0]+" --> "+m[i][1]+" ; "); 127 | } 128 | 129 | 130 | } 131 | 132 | private void printCostMatrix(double[][] cm) { 133 | for (int i = 0; i < cm.length; i++){ 134 | for (int j = 0; j < cm[0].length; j++){ 135 | System.out.print(cm[i][j]+"\t"); 136 | } 137 | System.out.println(); 138 | } 139 | 140 | } 141 | 142 | private double getMinimum(double[] distances) { 143 | double min = Double.MAX_VALUE; 144 | for (int i = 0; i < distances.length; i++){ 145 | if (distances[i] < min){ 146 | min = distances[i]; 147 | } 148 | } 149 | return min; 150 | } 151 | 152 | private double[][] copyMatrix(double[][] m) { 153 | double[][] copy = new double[m.length][m[0].length]; 154 | for (int i = 0; i < copy.length; i++){ 155 | for (int j = 0; j < copy[0].length; j++){ 156 | copy[i][j] = m[i][j]; 157 | } 158 | } 159 | return copy; 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /src/util/Gene.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class Gene implements Comparable{ 4 | 5 | private int[][] matching; 6 | 7 | public int[][] getMatching() { 8 | return matching; 9 | } 10 | 11 | private double distance; 12 | private double[][] cm; 13 | 14 | 15 | 16 | public double getDistance() { 17 | return distance; 18 | } 19 | 20 | public Gene(Graph sourceGraph, Graph targetGraph, int[][] m, 21 | CostFunction costFunction, EditDistance editDistance, double mutProb) { 22 | this.matching = m; 23 | for (int i = 0; i < this.matching.length; i++){ 24 | if (Math.random() < mutProb){ 25 | int j = this.matching[i][1]; 26 | int pick = (int) Math.floor(Math.random() * this.matching.length); 27 | this.matching[i][1] = this.matching[pick][1]; 28 | this.matching[pick][1] = j; 29 | } 30 | } 31 | this.distance = editDistance.getEditDistance( 32 | sourceGraph, targetGraph, this.matching, costFunction); 33 | 34 | } 35 | 36 | public Gene(Graph sourceGraph, Graph targetGraph, int[][] mergedMatching, 37 | CostFunction costFunction, EditDistance editDistance) { 38 | this.matching = mergedMatching; 39 | this.distance = editDistance.getEditDistance( 40 | sourceGraph, targetGraph, this.matching, costFunction); 41 | } 42 | 43 | public Gene(int[][] m, double d, double[][] cm) { 44 | this.matching = m; 45 | this.distance = d; 46 | this.setCm(cm); 47 | } 48 | 49 | public Gene(int[][] m, double d) { 50 | this.matching = m; 51 | this.distance = d; 52 | } 53 | 54 | public String toString(){ 55 | return "Distance: "+this.distance; 56 | } 57 | 58 | public void printMe(){ 59 | for (int i = 0; i < this.cm.length; i++){ 60 | for (int j = 0; j < this.cm[0].length; j++){ 61 | System.out.print(this.cm[i][j]+" "); 62 | } 63 | System.out.println(); 64 | } 65 | } 66 | 67 | @Override 68 | public int compareTo(Gene o) { 69 | 70 | if (this.distance > o.distance){ 71 | return 1; 72 | } else { 73 | return -1; 74 | } 75 | } 76 | 77 | public double[][] getCm() { 78 | return cm; 79 | } 80 | 81 | public void setCm(double[][] cm) { 82 | this.cm = cm; 83 | } 84 | 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/util/GeneticSearch.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | 4 | import java.util.Iterator; 5 | 6 | import java.util.TreeSet; 7 | 8 | import algorithms.BipartiteMatching; 9 | 10 | public class GeneticSearch { 11 | 12 | private Graph sourceGraph; 13 | private Graph targetGraph; 14 | private int[][] originalMatching; 15 | private CostFunction costFunction; 16 | private TreeSet pool; 17 | private TreeSet iterativeGenes; 18 | private EditDistance editDistance; 19 | private int popSize; 20 | private double[][] originalCostMatrix; 21 | private BipartiteMatching bipartiteMatching; 22 | private double mutProb; 23 | 24 | private static final int ITERATIONS = 6; 25 | 26 | private static final double PARENTS = 0.25; 27 | 28 | private static final int NUM_OF_FORBIDS = 15; 29 | 30 | private static final int SEEDS = 3; 31 | 32 | public GeneticSearch(Graph s, Graph t, int[][] m, CostFunction cf, EditDistance ed, int p, double[][] c, BipartiteMatching bm, double mp) { 33 | this.sourceGraph = s; 34 | this.targetGraph = t; 35 | this.originalMatching = m; 36 | this.costFunction = cf; 37 | this.editDistance = ed; 38 | this.popSize = p; 39 | this.originalCostMatrix = c; 40 | this.bipartiteMatching = bm; 41 | this.mutProb = mp; 42 | } 43 | 44 | public double searchBetter(double d) { 45 | double bestDist = Double.MAX_VALUE; 46 | this.getIterativeGenes(); 47 | for (int i = 0; i < SEEDS; i++){ 48 | this.makeInitialPool(); 49 | int lastChange = 0; 50 | int iteration = 0; 51 | 52 | while (iteration-lastChange < ITERATIONS){ 53 | // System.out.println("Iteration "+iteration+" : best Distance: "+this.pool.first().getDistance()); 54 | // this.printPool(); 55 | iteration++; 56 | TreeSet parents = this.selectParents(PARENTS); 57 | this.makeNewPopulation(parents); 58 | if (this.pool.first().getDistance() < bestDist){ 59 | lastChange = iteration; 60 | bestDist = this.pool.first().getDistance(); 61 | } 62 | } 63 | } 64 | // System.out.println("simply the best..."+bestDist); 65 | return bestDist; 66 | 67 | } 68 | 69 | private void getIterativeGenes() { 70 | this.iterativeGenes = new TreeSet(); 71 | // add original matching as gene to pool 72 | double distance = this.editDistance.getEditDistance(sourceGraph, 73 | targetGraph, this.originalMatching, costFunction); 74 | 75 | Gene gene = new Gene(this.originalMatching, distance, 76 | this.originalCostMatrix); 77 | this.iterativeGenes.add(gene); 78 | int[][] m = this.originalMatching; 79 | double[][] cm = this.copyMatrix(this.originalCostMatrix); 80 | for (int i = 0; i < NUM_OF_FORBIDS; i++) { 81 | int forbid = this.editDistance.getMaxCostMatch(); 82 | if (forbid > -1) { 83 | cm[forbid][m[forbid][1]] = Double.MAX_VALUE; 84 | } 85 | // compute the matching using Hungarian or VolgenantJonker (defined 86 | // in String matching) 87 | m = this.bipartiteMatching.getMatching(cm); 88 | // calculate the approximated edit-distance according to the 89 | // bipartite matching 90 | distance = this.editDistance.getEditDistance(sourceGraph, 91 | targetGraph, m, costFunction); 92 | gene = new Gene(m, distance, cm); 93 | 94 | this.iterativeGenes.add(gene); 95 | } 96 | } 97 | 98 | private void makeNewPopulation(TreeSet parents) { 99 | this.pool.clear(); 100 | Gene[] parentsArray = new Gene[parents.size()]; 101 | parents.toArray(parentsArray); 102 | this.pool.addAll(parents); 103 | for (int i = 0; i < this.popSize; i++){ 104 | int f = (int) (Math.random()*parents.size()); 105 | Gene father = parentsArray[f]; 106 | // System.out.println(">>>>>>> F: "+father); 107 | // father.printMe(); 108 | int m = (int) (Math.random()*parents.size()); 109 | Gene mother = parentsArray[m]; 110 | // System.out.println(">>>>>>> M: "+mother); 111 | // mother.printMe(); 112 | double[][] mergedCM = this.mergeCM(father, mother); 113 | int[][] mergedMatching = this.bipartiteMatching.getMatching(mergedCM); 114 | double distance = editDistance.getEditDistance( 115 | sourceGraph, targetGraph, mergedMatching, costFunction); 116 | Gene child = new Gene(mergedMatching, distance, mergedCM); 117 | // System.out.println(">>>>>>> C: "+child); 118 | // child.printMe(); 119 | this.pool.add(child); 120 | } 121 | } 122 | 123 | private double[][] mergeCM(Gene father, Gene mother) { 124 | double[][] mergedCM = new double[father.getCm().length][father.getCm()[0].length]; 125 | for (int i = 0; i < mergedCM.length; i++){ 126 | for (int j = 0; j < mergedCM[0].length; j++){ 127 | 128 | mergedCM[i][j] = Math.max(father.getCm()[i][j], mother.getCm()[i][j]); 129 | 130 | } 131 | } 132 | return mergedCM; 133 | } 134 | 135 | 136 | 137 | 138 | private TreeSet selectParents(double d) { 139 | TreeSet parents = new TreeSet(); 140 | Iterator poolIter = this.pool.iterator(); 141 | int i = 0; 142 | int max = (int) (d*this.pool.size()); 143 | while (poolIter.hasNext() && i < max){ 144 | parents.add(poolIter.next()); 145 | //i++; 146 | } 147 | return parents; 148 | } 149 | 150 | private void makeInitialPool() { 151 | this.pool = new TreeSet(); 152 | this.pool.addAll(this.iterativeGenes); 153 | double distance; 154 | double cm[][]; 155 | int[][] m = this.originalMatching.clone(); 156 | Gene gene; 157 | 158 | for (int p = 0; p < this.popSize-NUM_OF_FORBIDS; p++){ 159 | cm = this.copyMatrix(this.originalCostMatrix); 160 | for (int i = 0; i < m.length; i++){ 161 | if (Math.random() < this.mutProb){ 162 | if (i >= this.sourceGraph.size() && m[i][1] >= this.targetGraph.size()){ 163 | // do nothing: this is a eps-->eps matching 164 | } else { 165 | cm[i][m[i][1]] = Double.MAX_VALUE; 166 | } 167 | } 168 | } 169 | m = this.bipartiteMatching.getMatching(cm); 170 | distance = this.editDistance.getEditDistance( 171 | sourceGraph, targetGraph, m, costFunction); 172 | gene = new Gene(m, distance, cm); 173 | this.pool.add(gene); 174 | } 175 | } 176 | 177 | private double[][] copyMatrix(double[][] m) { 178 | double[][] copy = new double[m.length][m[0].length]; 179 | for (int i = 0; i < copy.length; i++){ 180 | for (int j = 0; j < copy[0].length; j++){ 181 | copy[i][j] = m[i][j]; 182 | } 183 | } 184 | return copy; 185 | } 186 | 187 | private void printPool(){ 188 | System.out.println("The current pool of genes:"); 189 | System.out.print("The best gene has distance: "); 190 | System.out.println(this.pool.first().getDistance()); 191 | Iterator iter = this.pool.iterator(); 192 | while (iter.hasNext()){ 193 | System.out.println("Gene-distances: "+iter.next().getDistance()); 194 | } 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /src/util/Graph.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package util; 5 | 6 | import java.util.Iterator; 7 | import java.util.LinkedList; 8 | 9 | /** 10 | * @author riesen 11 | * 12 | */ 13 | @SuppressWarnings("serial") 14 | public class Graph extends LinkedList{ 15 | 16 | /** the class of this graph */ 17 | private String className; 18 | 19 | /** the identifier of the graph */ 20 | private String graphID; 21 | private String fileName; 22 | 23 | 24 | 25 | /** directed or undirected edges */ 26 | private boolean directed; 27 | 28 | /** the adjacency-matrix of the graph */ 29 | private Edge[][] adjacencyMatrix; 30 | 31 | 32 | 33 | 34 | /** 35 | * Constructors 36 | */ 37 | public Graph(int n) { 38 | super(); 39 | this.adjacencyMatrix = new Edge[n][n]; 40 | } 41 | 42 | public Graph() { 43 | super(); 44 | } 45 | 46 | /** 47 | * generates a printable string of the graph 48 | */ 49 | public String toString(){ 50 | String graph = "*** Graph: "+this.graphID+" ***\n"; 51 | graph += "Class: "+this.className+"\n"; 52 | graph += "Nodes:\n"; 53 | Iterator iter = this.iterator(); 54 | while (iter.hasNext()){ 55 | Node node = iter.next(); 56 | graph += node.toString(); 57 | graph += "\n"; 58 | } 59 | graph += "\n"; 60 | graph += "Edges of...\n"; 61 | iter = this.iterator(); 62 | while (iter.hasNext()){ 63 | Node node = iter.next(); 64 | graph+="... Node: "+node.getNodeID()+": "; 65 | Iterator edgeIter = node.getEdges().iterator(); 66 | while (edgeIter.hasNext()){ 67 | Edge edge = edgeIter.next(); 68 | graph+=edge.getEdgeID()+"\t"; 69 | } 70 | graph+="\n"; 71 | } 72 | graph += "\n"; 73 | graph += "Adjacency Matrix:\n"; 74 | for (int i = 0; i < this.adjacencyMatrix.length; i++){ 75 | for (int j = 0; j < this.adjacencyMatrix.length; j++){ 76 | if (this.adjacencyMatrix[i][j] != null){ 77 | graph += "1"; 78 | } else { 79 | graph += "0"; 80 | } 81 | 82 | graph += "\t"; 83 | } 84 | graph += "\n"; 85 | } 86 | graph+="\n*** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"; 87 | return graph; 88 | } 89 | 90 | 91 | 92 | 93 | /** 94 | * getters and setters 95 | */ 96 | 97 | public String getClassName() { 98 | return className; 99 | } 100 | 101 | public void setClassName(String className) { 102 | this.className = className; 103 | } 104 | 105 | public String getGraphID() { 106 | return graphID; 107 | } 108 | 109 | public void setGraphID(String graphID) { 110 | this.graphID = graphID; 111 | } 112 | 113 | public boolean isDirected() { 114 | return directed; 115 | } 116 | 117 | public void setDirected(boolean directed) { 118 | this.directed = directed; 119 | } 120 | 121 | public Edge[][] getAdjacenyMatrix() { 122 | return adjacencyMatrix; 123 | } 124 | 125 | public void setAdjacenyMatrix(Edge[][] edges) { 126 | this.adjacencyMatrix = edges; 127 | } 128 | 129 | public void setFileName(String fileName) { 130 | this.fileName = fileName; 131 | } 132 | 133 | public String getFileName() { 134 | return fileName; 135 | } 136 | 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/util/GraphSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package util; 5 | 6 | import java.util.LinkedList; 7 | 8 | /** 9 | * @author riesen 10 | * 11 | */ 12 | @SuppressWarnings("serial") 13 | public class GraphSet extends LinkedList{ 14 | // dummy class 15 | } 16 | -------------------------------------------------------------------------------- /src/util/IndexAndCost.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class IndexAndCost implements Comparable{ 4 | 5 | private int index; 6 | 7 | private double cost; 8 | 9 | public IndexAndCost(int i, double c) { 10 | this.index = i; 11 | this.cost = c; 12 | } 13 | 14 | 15 | 16 | public int getIndex() { 17 | return index; 18 | } 19 | 20 | 21 | 22 | public double getCost() { 23 | return cost; 24 | } 25 | 26 | 27 | 28 | @Override 29 | public int compareTo(IndexAndCost other) { 30 | if (this.cost == other.cost){ 31 | return 0; 32 | } 33 | if (this.cost > other.cost){ 34 | return 1; 35 | } else { 36 | return -1; 37 | } 38 | } 39 | 40 | public String toString(){ 41 | return this.index+" "+this.cost; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/util/MatchingAndCost.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class MatchingAndCost implements Comparable{ 4 | 5 | private int from; 6 | public int getFrom() { 7 | return from; 8 | } 9 | 10 | public int getTo() { 11 | return to; 12 | } 13 | 14 | private int to; 15 | private double cost; 16 | 17 | public MatchingAndCost(int from, int to, double d) { 18 | this.from = from; 19 | this.to = to; 20 | this.cost = d; 21 | } 22 | 23 | @Override 24 | public int compareTo(MatchingAndCost other) { 25 | return (int) (this.cost - other.cost); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/util/Node.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package util; 5 | 6 | import java.util.HashMap; 7 | import java.util.Hashtable; 8 | import java.util.LinkedList; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author riesen 13 | * 14 | */ 15 | public class Node { 16 | 17 | /** the identifier of the node */ 18 | private String nodeID; 19 | 20 | /** the attributes of the node*/ 21 | private Hashtable attributes; 22 | 23 | /** the edges adjacent with this node */ 24 | private LinkedList edges; 25 | 26 | /** the centrality measures */ 27 | private double centralityMeasure; 28 | 29 | 30 | /** 31 | * Constructors 32 | */ 33 | public Node() { 34 | this.attributes = new Hashtable(); 35 | this.edges = new LinkedList(); 36 | } 37 | public Node(String id) { 38 | this.nodeID = id; 39 | } 40 | 41 | /** 42 | * generates a printable string of the node 43 | */ 44 | public String toString(){ 45 | String node = "NodeID = "+this.nodeID +"\n"; 46 | node += this.attributes; 47 | return node; 48 | } 49 | 50 | 51 | /** 52 | * puts a new attribute (key,value pair) 53 | * in the attribute-table 54 | */ 55 | public void put(String key, String value){ 56 | this.attributes.put(key, value); 57 | } 58 | 59 | /** 60 | * @return the attribute-value of 61 | * @param key 62 | */ 63 | public String getValue(String key){ 64 | return this.attributes.get(key); 65 | } 66 | 67 | 68 | 69 | /** 70 | * some getters and setters 71 | */ 72 | 73 | public String getNodeID() { 74 | return nodeID; 75 | } 76 | 77 | public void setNodeID(String nodeID) { 78 | this.nodeID = nodeID; 79 | } 80 | 81 | public LinkedList getEdges() { 82 | return edges; 83 | } 84 | 85 | public void setEdges(LinkedList edges) { 86 | this.edges = edges; 87 | } 88 | 89 | 90 | public void setCentrality(double score) { 91 | this.centralityMeasure = score; 92 | } 93 | 94 | 95 | public double getCentralityMeasure() { 96 | return this.centralityMeasure; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/util/ReverseGED.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | 4 | import java.util.Collections; 5 | import java.util.Iterator; 6 | import java.util.LinkedList; 7 | import java.util.TreeSet; 8 | 9 | public class ReverseGED { 10 | 11 | 12 | private Graph sourceGraph; 13 | private Graph targetGraph; 14 | private int[][] matching; 15 | private CostFunction costFunction; 16 | private EditDistance editDistance; 17 | private double distance; 18 | private double[][] costMatrix; 19 | private int s; 20 | private LinkedList indices; 21 | private int[][] originalMatching; 22 | 23 | 24 | public ReverseGED(Graph sourceGraph, Graph targetGraph, 25 | int[][] matching, CostFunction costFunction, 26 | EditDistance editDistance, double[][] costMatrix, double factor, double distance, int undirected, int s) { 27 | this.sourceGraph = sourceGraph; 28 | this.targetGraph = targetGraph; 29 | this.matching = matching; 30 | this.originalMatching = matching; 31 | this.costFunction = costFunction; 32 | this.editDistance = editDistance; 33 | this.distance = distance; 34 | this.costMatrix = costMatrix; 35 | this.s = s; 36 | this.indices = new LinkedList(); 37 | for (int i = 0; i < this.matching.length; i++){ 38 | this.indices.add(i); 39 | } 40 | } 41 | 42 | 43 | public double computeOtherApprox(){ 44 | // approximation is zero! 45 | if (this.distance <= 0.){ 46 | return 0; 47 | } 48 | // the successors of a node 49 | LinkedList successors ; 50 | 51 | // 52 | // list of edit paths (open) organized as TreeSet 53 | TreeSet open = new TreeSet(); 54 | 55 | 56 | 57 | // each treenode represents a solution (i.e. edit path) 58 | TreeNode start = new TreeNode(this.sourceGraph, this.targetGraph, this.editDistance, this.costFunction, this.matching, costMatrix); 59 | open.add(start); 60 | 61 | double bestSolution = start.getCost(); 62 | 63 | // System.out.println("START"); 64 | // System.out.println(start); 65 | 66 | // main loop of the search 67 | while (!open.isEmpty()){ 68 | // System.out.print("First: "); 69 | TreeNode u = open.pollFirst(); 70 | // System.out.println(u); 71 | // System.out.println("My successors:"); 72 | if (u.getDepth() < this.matching.length){ 73 | successors = u.generateReverseSuccessors(); 74 | bestSolution = this.checkSuccessors(successors, bestSolution); 75 | open.addAll(successors); 76 | while (open.size() > this.s){ 77 | open.pollLast(); 78 | } 79 | successors.clear(); 80 | } 81 | } 82 | return bestSolution; 83 | } 84 | 85 | 86 | private double checkSuccessors(LinkedList successors, 87 | double bestSolution) { 88 | Iterator iter = successors.iterator(); 89 | while (iter.hasNext()){ 90 | TreeNode tn = iter.next(); 91 | // System.out.println(tn); 92 | if (tn.getCost() < bestSolution){ 93 | bestSolution = tn.getCost(); 94 | } 95 | } 96 | return bestSolution; 97 | 98 | } 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | // private void printMatching() { 108 | // System.out.println("Matching"); 109 | // for (int i = 0; i < this.matching.length; i++){ 110 | // System.out.println(this.matching[i][0] +" -> "+this.matching[i][1]); 111 | // } 112 | // System.out.println(); 113 | // } 114 | 115 | 116 | private void shuffleMatching() { 117 | Collections.shuffle(this.indices); 118 | int[][] copyMatching = new int[this.matching.length][2]; 119 | for (int i = 0; i < this.matching.length; i++){ 120 | copyMatching[i][0] = this.originalMatching[this.indices.get(i)][0]; 121 | copyMatching[i][1] = this.originalMatching[this.indices.get(i)][1]; 122 | } 123 | this.matching = copyMatching; 124 | } 125 | 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/util/Swap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package util; 5 | 6 | import java.util.Arrays; 7 | import java.util.Iterator; 8 | import java.util.TreeSet; 9 | 10 | /** 11 | * @author riesen 12 | * 13 | */ 14 | public class Swap { 15 | 16 | private Graph sourceGraph; 17 | private Graph targetGraph; 18 | private int[][] originalMatching; 19 | private CostFunction costFunction; 20 | private EditDistance editDistance; 21 | private double[][] originalCostMatrix; 22 | 23 | private double theta = 0.3; 24 | private TreeSet pool; 25 | private int popSize = 100; 26 | 27 | private static final int ITERATIONS = 6; 28 | 29 | private static final double PARENTS = 0.25; 30 | 31 | private double mutProb = 0.5; 32 | 33 | private static final int SEEDS = 3; 34 | 35 | /** 36 | * 37 | */ 38 | public Swap(Graph sourceGraph, Graph targetGraph, 39 | int[][] matching, CostFunction costFunction, 40 | EditDistance editDistance, double[][] costMatrix) { 41 | this.sourceGraph = sourceGraph; 42 | this.targetGraph = targetGraph; 43 | this.originalMatching = matching; 44 | this.costFunction = costFunction; 45 | this.editDistance = editDistance; 46 | this.originalCostMatrix = costMatrix; 47 | } 48 | 49 | public double greedySearch(){ 50 | double d = this.editDistance.getEditDistance(this.sourceGraph, 51 | this.targetGraph, this.originalMatching, this.costFunction); 52 | int[] bestSwap = new int[4]; 53 | Arrays.fill(bestSwap, -1); 54 | boolean swapped = true; 55 | while (swapped){ 56 | swapped = false; 57 | for (int i = 0; i < this.originalMatching.length-1; i++){ 58 | int p = this.originalMatching[i][1]; 59 | // System.out.println("We investigate on "+i +" --> "+p); 60 | double c_ip = this.originalCostMatrix[i][p]; 61 | for (int j = i+1; j < this.originalMatching.length; j++){ 62 | int q = this.originalMatching[j][1]; 63 | // System.out.println("swap with "+j +" --> "+q); 64 | double c_jq = this.originalCostMatrix[j][q]; 65 | double c_iq = this.originalCostMatrix[i][q]; 66 | double c_jp = this.originalCostMatrix[j][p]; 67 | double totalCostOrig = c_ip + c_jq; 68 | double totalCostSwap = c_iq + c_jp; 69 | // System.out.println("The costs before the swap: "+totalCostOrig+" "+totalCostSwap+""); 70 | if (Math.abs(totalCostOrig - totalCostSwap) <= this.theta*totalCostOrig){ 71 | // System.out.println("Yes , we swap"); 72 | this.originalMatching[i][1] = q; 73 | this.originalMatching[j][1] = p; 74 | double d2 = this.editDistance.getEditDistance(this.sourceGraph, 75 | this.targetGraph, this.originalMatching, this.costFunction); 76 | if (d2 < d){ 77 | // System.out.println("Distance after swap is improved from "+d+" to "+d2); 78 | d = d2; 79 | bestSwap[0]=i; 80 | bestSwap[1]=p; 81 | bestSwap[2]=j; 82 | bestSwap[3]=q; 83 | swapped = true; 84 | 85 | } 86 | this.originalMatching[i][1] = p; 87 | this.originalMatching[j][1] = q; 88 | } 89 | } 90 | } 91 | if (swapped){ 92 | this.originalMatching[bestSwap[0]][1] = bestSwap[3]; 93 | this.originalMatching[bestSwap[2]][1] = bestSwap[1]; 94 | } 95 | } 96 | return d; 97 | } 98 | 99 | public double geneticSearch(){ 100 | double bestDist = Double.MAX_VALUE; 101 | for (int i = 0; i < SEEDS; i++){ 102 | this.makeInitialPool(); 103 | int lastChange = 0; 104 | int iteration = 0; 105 | // System.out.println("SEED: "+i); 106 | while (iteration-lastChange < ITERATIONS){ 107 | iteration++; 108 | TreeSet parents = this.selectParents(PARENTS); 109 | this.makeNewPopulation(parents); 110 | // System.out.println("Iteration "+iteration+" ; best distance: "+this.pool.first().getDistance()); 111 | if (this.pool.first().getDistance() < bestDist){ 112 | lastChange = iteration; 113 | 114 | bestDist = this.pool.first().getDistance(); 115 | // System.out.println("Improved "+bestDist); 116 | } 117 | } 118 | } 119 | return this.pool.first().getDistance(); 120 | } 121 | 122 | private void makeNewPopulation(TreeSet parents) { 123 | this.pool.clear(); 124 | this.pool.addAll(parents); 125 | // System.out.println("New Population is built: "+this.pool.size() +" are already in!"); 126 | Gene[] parentsArray = new Gene[parents.size()]; 127 | parents.toArray(parentsArray); 128 | while (this.pool.size() < this.popSize){ 129 | int f = (int) (Math.random()*parents.size()); 130 | Gene father = parentsArray[f]; 131 | int[][] m = this.copyMatrix(father.getMatching()); 132 | for (int i = 0; i < m.length-1; i++){ 133 | int p = m[i][1]; 134 | for (int j = i+1; j distance = "+d2); 153 | Gene gene = new Gene(m,d2); 154 | this.pool.add(gene); 155 | } 156 | } 157 | 158 | private void makeInitialPool() { 159 | // System.out.println("Making initial pool!"); 160 | this.pool = new TreeSet(); 161 | int[][] m = this.copyMatrix(this.originalMatching); 162 | double d = this.editDistance.getEditDistance(this.sourceGraph, 163 | this.targetGraph, this.originalMatching, this.costFunction); 164 | Gene original = new Gene(this.originalMatching, d); 165 | this.pool.add(original); 166 | for (int s = 0; s < this.popSize; s++){ 167 | m = this.copyMatrix(this.originalMatching); 168 | for (int i = 0; i < this.originalMatching.length-1; i++){ 169 | int p = m[i][1]; 170 | double c_ip = this.originalCostMatrix[i][p]; 171 | for (int j = i+1; j < this.originalMatching.length; j++){ 172 | int q = m[j][1]; 173 | double c_jq = this.originalCostMatrix[j][q]; 174 | double c_iq = this.originalCostMatrix[i][q]; 175 | double c_jp = this.originalCostMatrix[j][p]; 176 | double totalCostOrig = c_ip + c_jq; 177 | double totalCostSwap = c_iq + c_jp; 178 | if (Math.abs(totalCostOrig - totalCostSwap) < this.theta*totalCostOrig){ 179 | if (Math.random() < this.mutProb){ 180 | // System.out.println("Swapped!"); 181 | m[i][1] = q; 182 | m[j][1] = p; 183 | j = m.length; 184 | } 185 | } 186 | } 187 | } 188 | // System.out.println("*** Gene "+s); 189 | // this.printMatching(m); 190 | double d2 = this.editDistance.getEditDistance(this.sourceGraph, 191 | this.targetGraph, m, this.costFunction); 192 | // System.out.println("---> distance = "+d2); 193 | Gene gene = new Gene(m,d2); 194 | this.pool.add(gene); 195 | } 196 | } 197 | 198 | private void printMatching(int[][] m) { 199 | for (int i = 0; i < m.length; i++){ 200 | System.out.println(m[i][0] +" --> "+m[i][1]); 201 | } 202 | } 203 | 204 | private int[][] copyMatrix(int[][] m) { 205 | int[][] copy = new int[m.length][m[0].length]; 206 | for (int i = 0; i < copy.length; i++){ 207 | for (int j = 0; j < copy[0].length; j++){ 208 | copy[i][j] = m[i][j]; 209 | } 210 | } 211 | return copy; 212 | } 213 | 214 | private TreeSet selectParents(double d) { 215 | TreeSet parents = new TreeSet(); 216 | Iterator poolIter = this.pool.iterator(); 217 | int i = 0; 218 | int max = (int) (d*this.pool.size()); 219 | while (poolIter.hasNext() && i < max){ 220 | Gene g = poolIter.next(); 221 | parents.add(g); 222 | i++; 223 | } 224 | return parents; 225 | } 226 | 227 | 228 | 229 | 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/xml/XMLParser.java: -------------------------------------------------------------------------------- 1 | package xml; 2 | 3 | 4 | 5 | import java.io.FileReader; 6 | import java.util.Enumeration; 7 | import java.util.Vector; 8 | 9 | import nanoxml.XMLElement; 10 | import util.Edge; 11 | import util.Graph; 12 | import util.GraphSet; 13 | import util.Node; 14 | 15 | 16 | public class XMLParser { 17 | 18 | /** the path to the graph sets*/ 19 | private String graphPath; 20 | 21 | public void setGraphPath(String graphPath) { 22 | this.graphPath = graphPath; 23 | } 24 | 25 | 26 | 27 | 28 | /** 29 | * @return a graph set with 30 | * @param filename 31 | * @throws Exception 32 | */ 33 | public GraphSet parseCXL(String filename) throws Exception { 34 | XMLElement xml = new XMLElement(); 35 | FileReader reader = new FileReader(filename); 36 | xml.parseFromReader(reader); 37 | GraphSet graphSet = new GraphSet(); 38 | Vector children = xml.getChildren(); 39 | XMLElement root = children.get(0); 40 | Enumeration enumerator = root.enumerateChildren(); 41 | int i = 1; 42 | while (enumerator.hasMoreElements()) { 43 | 44 | XMLElement child = enumerator.nextElement(); 45 | Graph g = this.parseGXL(this.graphPath 46 | + child.getAttribute("file", null)+""); 47 | g.setFileName(child.getAttribute("file", null)+""); 48 | g.setClassName((String) child.getAttribute("class", "NO_CLASS")); 49 | graphSet.add(g); 50 | } 51 | return graphSet; 52 | } 53 | 54 | /** 55 | * @return a graph with 56 | * @param filename 57 | * @throws Exception 58 | */ 59 | public Graph parseGXL(String filename) throws Exception { 60 | 61 | XMLElement xml = new XMLElement(); 62 | FileReader reader = new FileReader(filename); 63 | xml.parseFromReader(reader); 64 | reader.close(); 65 | Graph graph1 = new Graph(); 66 | Vector children = xml.getChildren(); 67 | XMLElement root = (XMLElement) children.get(0); 68 | String id = (String) root.getAttribute("id", null); 69 | String edgemode = (String) root.getAttribute("edgemode", "undirected"); 70 | graph1.setGraphID(id); 71 | if (edgemode.equals("undirected")){ 72 | graph1.setDirected(false); 73 | } else { 74 | graph1.setDirected(true); 75 | } 76 | Enumeration enumerator = root.enumerateChildren(); 77 | int n = 0; 78 | while (enumerator.hasMoreElements()) { 79 | XMLElement child = (XMLElement) enumerator.nextElement(); 80 | if (child.getName().equals("node")) { 81 | String nodeId = (String) (child.getAttribute("id", null)); 82 | Node node = new Node(); 83 | node.setNodeID(nodeId); 84 | Enumeration enum1 = child.enumerateChildren(); 85 | while (enum1.hasMoreElements()) { 86 | XMLElement child1 = (XMLElement) enum1.nextElement(); 87 | if (child1.getName().equals("attr")) { 88 | String key = (String) child1.getAttribute("name", null); 89 | Vector children2 = child1.getChildren(); 90 | XMLElement child2 = (XMLElement) children2.get(0); 91 | String value = child2.getContent(); 92 | node.put(key, value); 93 | } 94 | 95 | } 96 | graph1.add(node); 97 | n++; 98 | } 99 | } 100 | Edge[][] edges = new Edge[n][n]; 101 | graph1.setAdjacenyMatrix(edges); 102 | enumerator = root.enumerateChildren(); 103 | while (enumerator.hasMoreElements()) { 104 | XMLElement child = (XMLElement) enumerator.nextElement(); 105 | if (child.getName().equals("edge")) { 106 | Edge edge = new Edge(); 107 | String from = (String) child.getAttribute("from", null); 108 | String to = (String) child.getAttribute("to", null); 109 | edge.put("from", from); 110 | edge.put("to", to); 111 | edge.setEdgeID(from + "_<>" + to); 112 | // ******************************* 113 | Enumeration enum1 = child.enumerateChildren(); 114 | while (enum1.hasMoreElements()) { 115 | XMLElement child1 = (XMLElement) enum1.nextElement(); 116 | if (child1.getName().equals("attr")) { 117 | String key = (String) child1.getAttribute("name", 118 | "key failed!"); 119 | Vector children2 = child1.getChildren(); 120 | XMLElement child2 = (XMLElement) children2.get(0); 121 | String value = child2.getContent(); 122 | edge.put(key, value); 123 | } 124 | } 125 | 126 | for (int i = 0; i < graph1.size(); i++){ 127 | Node nodeI = graph1.get(i); 128 | if (nodeI.getNodeID().equals(from)) { 129 | edge.setStartNode(nodeI); 130 | nodeI.getEdges().add(edge); 131 | for (int j = 0; j < graph1.size(); j++){ 132 | Node nodeJ = graph1.get(j); 133 | if (nodeJ.getNodeID().equals(to)) { 134 | edge.setEndNode(nodeJ); 135 | nodeJ.getEdges().add(edge); 136 | edges[i][j] = edge; 137 | if (!graph1.isDirected()){ 138 | edges[j][i] = edge; 139 | } 140 | } 141 | } 142 | } 143 | } 144 | } 145 | } 146 | 147 | return graph1; 148 | } 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | } 159 | --------------------------------------------------------------------------------