pax_global_header00006660000000000000000000000064120212211550014501gustar00rootroot0000000000000052 comment=e5cea66807a00b7685a2718489e102538106e1ec classycle-1.4/000077500000000000000000000000001202122115500133275ustar00rootroot00000000000000classycle-1.4/LICENSE.txt000066400000000000000000000024531202122115500151560ustar00rootroot00000000000000Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. classycle-1.4/README.html000066400000000000000000000015561202122115500151610ustar00rootroot00000000000000 Classycle: README
Classycle 1.4
=============


This distribution contains:


LICENSE.txt          Text of the BSD LICENSE.

README.html          This HTML page.

classycle.jar        All compiled Classycle classes.

reportXMLtoHTML.xsl  XSL transformation for XML reports

images/              Images needed by the report

docs/WebSite/        Folder with the complete content of
                     http://classycle.sourceforge.net 
                     including examples and API documentation.

src.zip              The zipped source code.
classycle-1.4/build.xml000066400000000000000000000103461202122115500151540ustar00rootroot00000000000000 classycle-1.4/dependencyCheckingTaskTestBuild.xml000066400000000000000000000101361202122115500222670ustar00rootroot00000000000000 # show allResults [A] = *A* [non-A] = example.* excluding [A] check [A] independentOf [non-A] check [non-A] independentOf [A] show allResults [A] = *A* [non-A] = ${package}.* excluding [A] check [A] independentOf [non-A] check [non-A] independentOf [A] check *A independentOf java.*.Ob* check ${package}.A* independentOf ${package}.B* check absenceOfClassCycles > 1 in ${package}.* {pckg} = example show allResults check absenceOfClassCycles > 1 in ${pckg}.* [A-not-p] = *A excluding example.p.* check [A-not-p] independentOf *h* *S* check example.B* example.p.* dependentOnlyOn java.lang.* example.A* [set] = example.B* example.p.* check [set] dependentOnlyOn java.lang.* check example.B* dependentOnlyOn *A [A-not-p] = *A excluding example.p.* check [A-not-p] independentOf *h* [A-not-p] = *A excluding example.p.* check [A-not-p] independentOf *h* bla bla show allResults classycle-1.4/images/000077500000000000000000000000001202122115500145745ustar00rootroot00000000000000classycle-1.4/images/abstract.png000066400000000000000000000014461202122115500171120ustar00rootroot00000000000000PNG  IHDR bKGD pHYs  ~tIME Q|*IDATxKHTQ6KM,R WB(+5)*V9F-k+ZJ",A RPЌPib9w洘f\ r9pKRJLlT L+6X BrL5r _BfauBYV*j @5ؕ rΕ{@d+X&3(Q:Vn%.J62<;wK~`Z),1/$ҭpTtx,‘VsRd~t1=5MWkI셹b"={S2!ӜP~gVKowC0AwdՊmF9k!؍-w^V%}=.ڑDdkֳځ;2A(Ft-% mi\IENDB`classycle-1.4/images/class.png000066400000000000000000000012671202122115500164150ustar00rootroot00000000000000PNG  IHDRZbKGD pHYs  ~tIME=DIDATxkSQƿM1Q1yAA\-APRN.8TZU0iE MQq21>r=y嵅zs.p=߽0u˘Aڄ;s93 0bmV +*7%3Ͷj'7 >^Up?L}ZP4f svjp6@(߼jԍFdflYΔ˺ ȉwkt8h]s>tE3fGT3gOsFjp{E~VZxvN ;6IAnu`jƒ $))IpKOEڤdS|o6B {r…CLZnk]ez2weLޕK-= RJT*bڝW#>Έh#|B$[&H>LR#^FDj+rbg! {1>)cC<kOr-h 7dZc~O՞MH '1\G~.AڦFܡ!&'+IENDB`classycle-1.4/images/inner.png000066400000000000000000000011621202122115500164150ustar00rootroot00000000000000PNG  IHDRZbKGD pHYs  ~tIME ^IDATxuAOAҖ,#ŋ`ڳg.!'0ƃ74<#1b$1aMzDC1*:;ov<ݝdvߛ3LkF'X j⸥O3,`E^1C,.@BKrA$4oɰ#׍٦Lt Ƒn/ˍ~* ޒ\;O{[U'X:TVI#:FL1r痋O<*OzOemї167BP7 ^Onqщ =TjXZ]CD(wKO$2%}y::ˋX#l+(~'eB{F"|T[ ^ܙ05\`vj;54 %9άmǂ\hy6'UGfLIzrav1-;܁AoK ɛgsjh|<5C>66{qi<.$&;}}6]'$ZBs~5H/x?$ux %tuSR|CV;_xw򜧷Toޓ@ )";Yݚݐ'XYYɲH@.L+U{nnM$@JA^R18XnMN0L*33Yx۷JJ"/QoB^q} U/ʠW5FO.bVrrh$NWYi!Щ$.jn PC nMƻi[h%qi)0vbw;1)RnRЙL}Lп#.E"xfmY D {zMgmڱ!,@6}̑Q܃,,b"Q̋++ZZ:p$+n k*X8zSHoWxyw|Vp0? sc?ÇӕӦ칲^li)XoTN:.`PC*å SI ZRiۇ59~žDcIENDB`classycle-1.4/images/interface.png000066400000000000000000000012621202122115500172430ustar00rootroot00000000000000PNG  IHDR bKGD pHYs  ~tIME,?IDATxԿOSQmJH ".\`&0:?8 dԈLt2HhL +%J}ǡgoz=sc[Hr{ E!R* ZMC q mhDk05R[>Crg]]JrXajs)Q}M{L$4mHg2䀋41)({<#Qhjz~vz[C;bΘ)wDTP=5ch.H4a/Y>xl :xx/M1 MN~v6V6cwa>a,y Ń`Q Rr!?~7FO..oؕ oXmӸ?kx< :cGÏbMu >{ce~ʦA4NhIENDB`classycle-1.4/images/link.png000066400000000000000000000002071202122115500162360ustar00rootroot00000000000000PNG  IHDRKm)bKGD pHYs  ~tIME -6kGIDATxc\`*:h%@5IENDB`classycle-1.4/images/logo.png000066400000000000000000000164771202122115500162610ustar00rootroot00000000000000PNG  IHDRSV'bKGD pHYs  ~tIME RIDATxyU?m-a&Y#`) EE6g@" P@) xEf*BnA]@a)-欄̜}7ɛy1-tpy[#AA{SI Ǜs_Kq5mrŰm't^DoA6EO䯠'G`ݨ4ϪtՁ>ȿ x*&p&=>+M@;Ss't4}788'rd!p^:sjNo/]6Вs1Z.=Ob ^ȑK'k[IKi슴>^5tpP*})#a+r8nak7Y@vF*ևQCnhC`Nt? /0rd-\ܠi?M܃`{"4DOJK)O;Lt>р-NE y/to a. 4clCeT9VCniirpr{8 %ɁBmJ+ PmĭpTf7ъ:;C\.=,ݭ,J>[V#H;fүRgUn.r8ZI@~f~aIN_֍_1J*/p>2}yZCqLȿ_<~CNlJ7Y0`3hD׷#݈w"v `|]78:ϧ_LoQ(&cp81`=Ep^:=wsG,~ʕSy6Q7K@CG/ոU۵ダq(rHBhtEw'pt&<ǡ%F?WOk(Ixk)&xQ 3w}@6is`xxlS9eO࿀QmCfi  AtqVG7Ѳ`Wً}t6]AJ_ȯP,ae>p=\PgpҚl>cXZ>(h)*y~SGc Q"WMLWi[cn0i Uv9PKWg M":Nm?K>~CC GZPwC!Y#`7#+u6pnp6^Ʒ֧̋`~!]qfLR@mBn`b,q7CIs"ɏɾSǵ-ͻ(K{(z1* ɓSVB3O#j7e(R/dik3|B&V*;R5Jꪧϣr 0Lv&@i|$(dwEqpVCO8w9>~4>c1G^ wX!.Xfb@o?7/[9 e?:89*g 'h>Lu$B"mdXn9/:0|nT9ʽL놶PȘ}HYd=%خE8.K'RQv10+pp#{R%>NJk^vk? 9qYf |f3IRW=}O4[ᴣ _n8~:;houx5 scx଍Tỉ\HY r=\dX G*|ѴH!(s\K2pf!)~r!}< e_)bzYT>>A T 2OSܥ$}L9'Ylώtp2vq&88[#p뀓}(ǟcG(P\ǵ>~\&˱ hYdSH:}{84':.4r0IL`B&[(wR!].D2 lŲB& O}Y'vl I*}yٝUMtJ$ aܷq$WƂF>gH@&k) QNǿbq-ed^Fˬ}f1q^Kkl@E,W"Lv.pZ1|**eCT>T>Ws1rpƎ4{=zJ|pDs 3W?Ʊ$K?^,?E;ق>fӇ[䫵YىLGELxe$KnӀgR4 Wde]ju|L<M@(,%D1bO cǿvU0;8&7#W1&oUñ4{FR/QzG`Kbvvp5$_r1Rcp ^ҒCЗә$ {EUK"n8;[d ג@F"(2`Rga*Q&2ٸk/ppljT~D6hՁqלe88#!@MVr:8B88 B|]⥗'7 һq qq En& 8//&ߠ"(d@8[#mї(ϭqk4oOD__Is~&K|q37cKsCI0t,ǥyE#/ײP R01~ h;9:*E~QwBh)}.t%"q[9 F $D9J߿K?0n ]qDFKr.ܟ2acXqIWg T>w fR- 2ٚgC}3ХU>3[" 麞\mM޼.ȏ*? ЎAcq)>~=/SHw4 -h);J%F%8&2٧Sܭ wrhUqg_}d ~ÑYJjwVs.Z]?xmKߋ&HG_eLB&dB&{%qx|jɞ6o3Z~lYd7F:m^Mq 2]9|d%t㿈 /Vi~?/Jwgm> >~!ȓndlt>}i˪ pO H2na!V YK,n:VH/O삾WFcH~B-X>\x_ 5)FJ*\}ak!Η.8Y W[u:.r"%H+ƃXs ImV8RԼBm!V@ڍ0ړI5ڑ(ɨi8 :فl+}GqV@ڈs~1ƎH8>DatQy x"zc歀#5u57 ;f(L@2`%Z,]@?Z{9$0-$N"Z4"/xȧ BnA/#-Th !ݶZC "[|M%[usO=KG ^/RLŲ"EofߑT{,PͲt5kЌq9Cچ]QI$n0ժ@7^JUF;}5HkݙS'?I)U>r;U9` =/jCqi/Hm񎢓 B7F%'"m_S(h]|/]Kmh?{8R.jUX( 7P1z񺃇 Cok 6C zz8K ʸ`+ɵO+Z`-! |> `/tu:+ d'Вk Ri\T3# `$^no/ H; !s2a 퀗7 γ?.vQ?vi7`w ,E|"K>^v DZr -bX,bX,bX,bX,bX,A9fIENDB`classycle-1.4/images/mix.png000066400000000000000000000015161202122115500161020ustar00rootroot00000000000000PNG  IHDRZbKGD pHYs  ~tIME *]6IDATxmTMHTa=93Lhe)i10+AEQFR-[$ Zm]e!e1/) gtRG{};s˽Go]ˎ|+E۾rp2{IRK|^}d`OX?ʪ%{g0ak=}aݹga>%߿B,.k 7[IENDB`classycle-1.4/images/package.png000066400000000000000000000015771202122115500167070ustar00rootroot00000000000000PNG  IHDR bKGD pHYs  ~tIME 7,tEXtCommentCreated with The GIMPd%nIDATxڅ?lG,P?EH\@[w)"GH EE(h$(#BRAV;q]ٝG13{QVf7*V&b6A` ZTЊi I@:& ՈQaTJ@u$hD E#֠p@y Q :uDSq0"b`9L4tf@-HNEEBlP}lg,2DsMʷUj89ŵrXP߼ih*ޑ?TqΜ8LGLL_ƭ_ P I ۞AY.9 K1ض3rh4X471X𳼃 6m:YZdDv!@>ΫGC,<1MĠ0f j }w ӓ_ GRbP]E`X~_bL,@GLҥD{ <ضyg?$>`Oa4Wo 4aG%""ڗjRkFUtief_q<\xJo]$q*+U %Q! ͥ:yk&28*1GFmc[3Cv S-zW9Him]߅arI>j!lk;snZ^um!VSWQq! ߧ*QAԚ?/-cE2IENDB`classycle-1.4/reportTaskTestBuild.xml000066400000000000000000000060151202122115500200310ustar00rootroot00000000000000 classycle-1.4/reportXMLtoHTML.xsl000066400000000000000000001016231202122115500170060ustar00rootroot00000000000000 ]> Click on behind a number and a window will pop up showing more details. Classycle Analysis of <xsl:value-of select="/classycle/@title"/>

Classcyle Analysis of

Date:

Summary

no class cycles class cycle class cycles
class layers
classes (using external classes) grouped in packages
no package cycles package cycle package cycles
no package packages

Interfaces Abstract classes Concrete classes
Type Number of classes Averaged (maximum) size in bytes Averaged (maximum) number of usage by other classes Averaged (maximum) number of used internal classes Averaged (maximum) number of used external clasess

Cycles

Name Number of classes Best Fragment Size Girth Radius Diameter Layer

Package Cycles

Name Number of packagess Best Fragment Size Girth Radius Diameter Layer

Layers

Layer
Number of classes Classes of layer :

Classes and Packages

Click on or to go to the cycle to which the class/package belongs.
Class/Package Size Used by Uses internal Uses external Layer Source(s)
# Member of cycle Classes using : uses: true uses: Packages using : uses: true uses:
inner class class inner class class inner class class package class inner class Classes of cycle : Best fragmenter(s) of cycle : Center classes of cycle : package Packages of cycle : Best fragmenter(s) of cycle : Center packages of cycle : cursor:pointer; javascript:showTable(" ",""," ; ") cursor:pointer; javascript:showTable(" ","Name,Maximum fragment size,Eccentricity"," , , ; ") <div class='link' onclick='javascript:window.opener.location.href=\"# \"'> </div> % # () # () # () # ()
classycle-1.4/src/000077500000000000000000000000001202122115500141165ustar00rootroot00000000000000classycle-1.4/src/classycle/000077500000000000000000000000001202122115500161005ustar00rootroot00000000000000classycle-1.4/src/classycle/Analyser.java000066400000000000000000000507601202122115500205310ustar00rootroot00000000000000/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import classycle.graph.AtomicVertex; import classycle.graph.StrongComponent; import classycle.graph.StrongComponentAnalyser; import classycle.renderer.AtomicVertexRenderer; import classycle.renderer.PlainStrongComponentRenderer; import classycle.renderer.StrongComponentRenderer; import classycle.renderer.TemplateBasedClassRenderer; import classycle.renderer.XMLClassRenderer; import classycle.renderer.XMLStrongComponentRenderer; import classycle.util.StringPattern; import classycle.util.Text; import classycle.util.TrueStringPattern; /** * Main class of the Classycle tool. Runs on the command line and * produces a report. * * @author Franz-Josef Elmer */ public class Analyser { private static final String VERSION = "1.4"; private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private static final String CSV_TEMPLATE = "{0},{1},{3},{2},{4},{5},{6},{7},{8},{9}\n"; private final String[] _classFiles; private final StringPattern _pattern; private final StringPattern _reflectionPattern; private final boolean _mergeInnerClasses; private StrongComponentAnalyser _classAnalyser; private StrongComponentAnalyser _packageAnalyser; /** * Creates an instance for the specified files or folders. * @param classFiles Absolute or relative file names. */ public Analyser(String[] classFiles) { this(classFiles, new TrueStringPattern(), null, false); } /** * Creates an instance for the specified files or folders which are * filtered by the specified {@link StringPattern} object. * @param classFiles Absolute or relative file names. * @param pattern Pattern fully-qualified class name have to match in order * to be a part of the class graph. * @param reflectionPattern Pattern ordinary string constants of a class * file have to fullfill in order to be handled as a class references. * In addition such strings have to be syntactically valid * fully qualified class names. If null ordinary string * constants will not be checked. * @param mergeInnerClasses If true * merge inner classes with its outer class */ public Analyser(String[] classFiles, StringPattern pattern, StringPattern reflectionPattern, boolean mergeInnerClasses) { _classFiles = classFiles; _pattern = pattern; _reflectionPattern = reflectionPattern; _mergeInnerClasses = mergeInnerClasses; } /** * Parses the class files and creates the class graph. * @return the duration of this operation in milliseconds. * @throws IOException if a problem occured during reading */ public long createClassGraph() throws IOException { long time = System.currentTimeMillis(); AtomicVertex[] classGraph = Parser.readClassFiles(_classFiles, _pattern, _reflectionPattern, _mergeInnerClasses); _classAnalyser = new StrongComponentAnalyser(classGraph); return System.currentTimeMillis() - time; } /** * Returns the class graph. Invokes {@link #createClassGraph()} if not * already invoked. */ public AtomicVertex[] getClassGraph() { if (_classAnalyser == null) { try { createClassGraph(); } catch (IOException e) { throw new RuntimeException(e.toString()); } } return _classAnalyser.getGraph(); } /** * Counts the number of external classes. */ public int getNumberOfExternalClasses() { AtomicVertex[] graph = getClassGraph(); HashSet usedClasses = new HashSet(); int result = 0; for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = graph[i]; for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) { ClassAttributes attributes = (ClassAttributes) vertex.getHeadVertex(j).getAttributes(); if (attributes.getType() == ClassAttributes.UNKNOWN) { if (!usedClasses.contains(attributes.getName())) { result++; usedClasses.add(attributes.getName()); } } } } return result; } /** * Condenses the class graph to an acyclic graph of its strong components. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public long condenseClassGraph() { checkClassGraph("condenseClassGraph()"); long time = System.currentTimeMillis(); _classAnalyser.getCondensedGraph(); return System.currentTimeMillis() - time; } /** * Returns the condensed the class graph, i.e. the acyclic graph of * its strong components. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public StrongComponent[] getCondensedClassGraph() { checkClassGraph("getCondenseClassGraph()"); return _classAnalyser.getCondensedGraph(); } /** * Calculates the for each class its layer index. The layer index of a * class is the length of the longest path in the acyclic graph of strong * components starting at the strong component to which the class belongs. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public long calculateClassLayerMap() { checkClassGraph("calculateClassLayerMap()"); long time = System.currentTimeMillis(); _classAnalyser.getLayerMap(); return System.currentTimeMillis() - time; } /** * Calculates the for each class its layer index and returns * a Map where the classes are the keys (type {@link AtomicVertex}) * and the layer indices are the values (type Integer). * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public Map getClassLayerMap() { checkClassGraph("getClassLayerMap()"); return _classAnalyser.getLayerMap(); } /** * Creates the package graph from the class graph. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public long createPackageGraph() { checkClassGraph("createPackageGraph()"); long time = System.currentTimeMillis(); PackageProcessor processor = new PackageProcessor(); processor.deepSearchFirst(_classAnalyser.getGraph()); _packageAnalyser = new StrongComponentAnalyser(processor.getGraph()); return System.currentTimeMillis() - time; } /** * Prints a CSV report into the specified writer. Delimiter is ','. * First, a header with column titles is print. The columns are *
  1. class name *
  2. inner class (false or true) *
  3. size (in bytes) *
  4. used by (number of classes using this class) *
  5. uses internal classes * (number of classes of the graph used by this class) *
  6. uses external classes * (number of external classes used by this class) *
  7. layer index *
* @param writer Output stream. */ public void printCSV(PrintWriter writer) { StrongComponent[] cycles = getCondensedClassGraph(); AtomicVertex[] graph = getClassGraph(); Map map = getClassLayerMap(); writer.println("class name,type,inner class,size,used by," + "uses internal classes,uses external classes," + "layer index,cycle,source"); render(graph, cycles, map, new TemplateBasedClassRenderer(CSV_TEMPLATE), writer); writer.close(); } /** * Prints for each class a raw output into the specified writer. * This output includes all classes used by the class. * @param writer Output stream. */ public void printRaw(PrintWriter writer) { AtomicVertex[] graph = getClassGraph(); for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = graph[i]; writer.println(vertex.getAttributes()); for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) { writer.println(" " + vertex.getHeadVertex(j).getAttributes()); } } writer.close(); } /** * Prints for each strong component of the class graph a raw output into * the specified writer. The strong component must have at least * minSize classes in order to be printed out. * This output includes all classes of the strong component. * @param writer Output stream. * @param minSize Minimum size of the strong component. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public void printComponents(PrintWriter writer, int minSize) { checkClassGraph("printComponents()"); StrongComponent[] components = getCondensedClassGraph(); StrongComponentRenderer renderer = new PlainStrongComponentRenderer(); for (int i = 0; i < components.length; i++) { StrongComponent component = components[i]; if (component.getNumberOfVertices() >= minSize) { writer.println(renderer.render(component)); } } writer.close(); } private void checkClassGraph(String method) { if (_classAnalyser == null) { throw new IllegalStateException( method + " should be invoked after createClassGraph()."); } } /** * Returns the package graph created the class graph. * @throws IllegalStateException if this method is called before * {@link #createClassGraph()}. */ public AtomicVertex[] getPackageGraph() { if (_packageAnalyser == null) { createPackageGraph(); } return _packageAnalyser.getGraph(); } /** * Condenses the package graph to an acyclic graph of its strong components. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createPackageGraph()}. */ public long condensePackageGraph() { checkPackageGraph("condensePackageGraph()"); long time = System.currentTimeMillis(); _packageAnalyser.getCondensedGraph(); return System.currentTimeMillis() - time; } /** * Returns the condensed package graph, i.e. the acyclic graph of * its strong components. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createPackageGraph()}. */ public StrongComponent[] getCondensedPackageGraph() { checkPackageGraph("getCondensedPackageGraph()"); return _packageAnalyser.getCondensedGraph(); } /** * Calculates the for each package its layer index. The layer index of a * package is the length of the longest path in the acyclic graph of strong * components starting at the strong component to which the package belongs. * @return the duration of this operation in milliseconds. * @throws IllegalStateException if this method is called before * {@link #createPackageGraph()}. */ public long calculatePackageLayerMap() { checkPackageGraph("calculatePackageLayerMap()"); long time = System.currentTimeMillis(); _packageAnalyser.getLayerMap(); return System.currentTimeMillis() - time; } /** * Calculates the for each package its layer index and returns * a Map where the packages are the keys (type {@link AtomicVertex}) * and the layer indices are the values (type Integer). * @throws IllegalStateException if this method is called before * {@link #createPackageGraph()}. */ public Map getPackageLayerMap() { checkPackageGraph("getPackageLayerMap()"); return _packageAnalyser.getLayerMap(); } /** * Reads and analyses class files. Does only package analysis if * packagesOnly == true. Reports progress of analysis on * System.out. * @throws IOException in case of reading problems. */ public void readAndAnalyse(boolean packagesOnly) throws IOException { System.out.println("============= Classycle V" + VERSION + " ============="); System.out.println("========== by Franz-Josef Elmer =========="); System.out.print("read class files and create class graph ... "); long duration = createClassGraph(); System.out.println("done after " + duration + " ms: " + getClassGraph().length + " classes analysed."); if (!packagesOnly) { // Condense class graph System.out.print("condense class graph ... "); duration = condenseClassGraph(); System.out.println("done after " + duration + " ms: " + getCondensedClassGraph().length + " strong components found."); // Calculate class layer System.out.print("calculate class layer indices ... "); duration = calculateClassLayerMap(); System.out.println("done after " + duration + " ms."); } System.out.print("create package graph ... "); duration = createPackageGraph(); System.out.println("done after " + duration + " ms: " + getPackageGraph().length + " packages."); // Condense package graph System.out.print("condense package graph ... "); duration = condensePackageGraph(); System.out.println("done after " + duration + " ms: " + getCondensedPackageGraph().length + " strong components found."); // Calculate package layer System.out.print("calculate package layer indices ... "); duration = calculatePackageLayerMap(); System.out.println("done after " + duration + " ms."); } /** * Prints an XML report into the specified writer. * @param title Title of the report. * @param packagesOnly if true classes are omitted. * @param writer Output stream. * @throws IllegalStateException if this method is called before * {@link #createPackageGraph()}. */ public void printXML(String title, boolean packagesOnly, PrintWriter writer) { checkPackageGraph("printXML()"); writer.println(""); writer.println(""); writer.print(""); if (!packagesOnly) { StrongComponent[] components = getCondensedClassGraph(); writer.println(" "); StrongComponentRenderer sRenderer = new XMLStrongComponentRenderer(2); for (int i = 0; i < components.length; i++) { writer.print(sRenderer.render(components[i])); } writer.println(" "); writer.println(" "); AtomicVertex[] graph = getClassGraph(); Map layerMap = getClassLayerMap(); render(graph, components, layerMap, new XMLClassRenderer(), writer); writer.println(" "); } StrongComponent[] components = getCondensedPackageGraph(); writer.println(" "); StrongComponentRenderer sRenderer = new XMLPackageStrongComponentRenderer(2); for (int i = 0; i < components.length; i++) { writer.print(sRenderer.render(components[i])); } writer.println(" "); writer.println(" "); AtomicVertex[] graph = getPackageGraph(); Map layerMap = getPackageLayerMap(); render(graph, components, layerMap, new XMLPackageRenderer(), writer); writer.println(" "); writer.println(""); writer.close(); } private void render(AtomicVertex[] graph, StrongComponent[] cycles, Map layerMap, AtomicVertexRenderer renderer, PrintWriter writer) { List list = getTrueCycles(cycles); for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = graph[i]; Integer layerIndex = (Integer) layerMap.get(vertex); writer.print(renderer.render(vertex, getCycleFor(vertex, list), layerIndex == null ? -1 : layerIndex.intValue())); } } private List getTrueCycles(StrongComponent[] cycles) { List list = new ArrayList(); if (cycles != null) { for (int i = 0; i < cycles.length; i++) { if (cycles[i].getNumberOfVertices() > 1) { list.add(cycles[i]); } } } return list; } private StrongComponent getCycleFor(AtomicVertex vertex, List cycles) { for (int i = 0, n = cycles.size(); i < n; i++) { StrongComponent cycle = (StrongComponent) cycles.get(i); for (int j = 0, m = cycle.getNumberOfVertices(); j < m; j++) { if (cycle.getVertex(j) == vertex) { return cycle; } } } return null; } private void checkPackageGraph(String method) { if (_packageAnalyser == null) { throw new IllegalStateException( method + " should be invoked after createPackageGraph()."); } } /** * Main method of the Analyser. Prints on the console its usage if * some invalid command line argument occurs or is missed. * @param args command line arguments. * @throws Exception */ public static void main(String[] args) throws Exception { AnalyserCommandLine commandLine = new AnalyserCommandLine(args); if (!commandLine.isValid()) { System.out.println("Usage: java -jar classycle.jar " + commandLine.getUsage()); System.exit(0); } Analyser analyser = new Analyser(commandLine.getClassFiles(), commandLine.getPattern(), commandLine.getReflectionPattern(), commandLine.isMergeInnerClasses()); analyser.readAndAnalyse(commandLine.isPackagesOnly()); // Create report(s) if (commandLine.getXmlFile() != null) { analyser.printXML(commandLine.getTitle(), commandLine.isPackagesOnly(), new PrintWriter(new FileWriter(commandLine.getXmlFile()))); } if (commandLine.getCsvFile() != null) { analyser.printCSV( new PrintWriter(new FileWriter(commandLine.getCsvFile()))); } if (commandLine.isRaw()) { analyser.printRaw(new PrintWriter(System.out)); } if (commandLine.isCycles() || commandLine.isStrong()) { analyser.printComponents(new PrintWriter(System.out), commandLine.isCycles() ? 2 : 1); } } } //class classycle-1.4/src/classycle/AnalyserCommandLine.java000066400000000000000000000106221202122115500226310ustar00rootroot00000000000000/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; /** * Process command line arguments and options for the main application * {@link Analyser}. * * @author Franz-Josef Elmer */ public class AnalyserCommandLine extends CommandLine { private static final String XML_FILE = "-xmlFile="; private static final String CSV_FILE = "-csvFile="; private static final String TITLE = "-title="; private boolean _packagesOnly; private boolean _raw; private boolean _cycles; private boolean _strong; private String _title; private String _xmlFile; private String _csvFile; public AnalyserCommandLine(String[] args) { super(args); if (_title == null && _classFiles.length > 0) { _title = _classFiles[0]; } } protected void handleOption(String argument) { if (argument.equals("-raw")) { _raw = true; } else if (argument.equals("-packagesOnly")) { _packagesOnly = true; } else if (argument.equals("-cycles")) { _cycles = true; } else if (argument.equals("-strong")) { _strong = true; } else if (argument.startsWith(TITLE)) { _title = argument.substring(TITLE.length()); if (_title.length() == 0) { _valid = false; } } else if (argument.startsWith(XML_FILE)) { _xmlFile = argument.substring(XML_FILE.length()); if (_xmlFile.length() == 0) { _valid = false; } } else if (argument.startsWith(CSV_FILE)) { _csvFile = argument.substring(CSV_FILE.length()); if (_csvFile.length() == 0) { _valid = false; } } else { super.handleOption(argument); } } /** Returns the usage of correct command line arguments and options. */ public String getUsage() { return "[-raw] [-packagesOnly] [-cycles|-strong] " + "[" + XML_FILE + "] [" + CSV_FILE + "] " + "[" + TITLE + "] " + super.getUsage(); } /** Returns <tt>true</tt> if the option <tt>-cycles</tt> has been set. */ public boolean isCycles() { return _cycles; } /** Returns <tt>true</tt> if the option <tt>-package</tt> has been set. */ public boolean isPackagesOnly() { return _packagesOnly; } /** Returns <tt>true</tt> if the option <tt>-raw</tt> has been set. */ public boolean isRaw() { return _raw; } /** Returns <tt>true</tt> if the option <tt>-strong</tt> has been set. */ public boolean isStrong() { return _strong; } /** * Returns the name of the CSV file as defined by the option * <tt>-csvFile</tt>. * @return <tt>null</tt> if undefined. */ public String getCsvFile() { return _csvFile; } /** * Returns the title by the option <tt>-title</tt>. * If undefined {@link #getClassFiles()}<tt>[0]</tt> will be used. * @return String */ public String getTitle() { return _title; } /** * Returns the name of the XML file as defined by the option * <tt>-xmlFile</tt>. * @return <tt>null</tt> if undefined. */ public String getXmlFile() { return _xmlFile; } } ��������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/ClassAttributes.java����������������������������������������������������0000664�0000000�0000000�00000012312�12021221155�0022056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; /** * Immutable class holding the attributes of a class vertex. They are * <ul><li>fully-qualified class name * <li>type (interface, abstract, concrete, unknown) * <li>flag <tt>innerClass</tt> * <li>size of the class file * </ul> * * @author Franz-Josef Elmer */ public class ClassAttributes extends NameAndSourceAttributes { /** Type constant. */ public static final String INTERFACE = "interface", ABSTRACT_CLASS = "abstract class", CLASS = "class", UNKNOWN = "unknown external class"; private final String _type; private final boolean _innerClass; private final int _size; /** * Creates an instance based on the specified name, type, and size. * The innerclass flag will be set if the name contains a '$' character. * @param name Fully-qualified class name. * @param source Optional source of the class file. Can be <code>null</code>. * @param type Type. * @param size Size. */ public ClassAttributes(String name, String source, String type, int size) { super(name); if (source != null) { addSource(source); } _type = type; _innerClass = name != null && name.indexOf('$') > 0; _size = size; } /** * Creates an instance of the type {@link #INTERFACE}. * @param name Fully-qualified class name. * @param source Optional source of the class file. Can be <code>null</code>. * @param size Size of the class file. * @return a new instance. */ public static ClassAttributes createInterface(String name, String source, int size) { return new ClassAttributes(name, source, INTERFACE, size); } /** * Creates an instance of the type {@link #ABSTRACT_CLASS}. * @param name Fully-qualified class name. * @param source Optional source of the class file. Can be <code>null</code>. * @param size Size of the class file. * @return a new instance. */ public static ClassAttributes createAbstractClass(String name, String source, int size) { return new ClassAttributes(name, source, ABSTRACT_CLASS, size); } /** * Creates an instance of the type {@link #CLASS}. * @param name Fully-qualified class name. * @param source Optional source of the class file. Can be <code>null</code>. * @param size Size of the class file. * @return a new instance. */ public static ClassAttributes createClass(String name, String source, int size) { return new ClassAttributes(name, source, CLASS, size); } /** * Creates an instance of the type {@link #UNKNOWN}. * @param name Fully-qualified class name. * @param size Size of the class file. * @return a new instance. */ public static ClassAttributes createUnknownClass(String name, int size) { return new ClassAttributes(name, null, UNKNOWN, size); } /** * Returns the class type. * @return either {@link #INTERFACE}, {@link #ABSTRACT_CLASS}, * {@link #CLASS}, or {@link #UNKNOWN}. */ public String getType() { return _type; } /** Returns <tt>true</tt> in the case of an inner class. */ public boolean isInnerClass() { return _innerClass; } /** Returns the size of the class file in bytes. */ public int getSize() { return _size; } /** Returns the attributes as a string for pretty printing. */ public String toString() { StringBuffer buffer = new StringBuffer(_innerClass ? "inner " : ""); buffer.append(_type).append(' ').append(getName()); if (_size > 0) { buffer.append(" (").append(_size).append(" bytes)"); } String sources = getSources(); if (sources.length() > 0) { buffer.append(" sources: ").append(sources); } return new String(buffer); } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/ClassNameExtractor.java�������������������������������������������������0000664�0000000�0000000�00000012647�12021221155�0022517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Created on 24.09.2006 */ package classycle; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import classycle.classfile.UTF8Constant; class ClassNameExtractor { /** Returns <tt>true</tt> if <tt>className</tt> is a valid class name. */ static boolean isValid(String className) { boolean valid = true; boolean firstCharacter = true; for (int i = 0, n = className.length(); valid && i < n; i++) { char c = className.charAt(i); if (firstCharacter) { firstCharacter = false; valid = Character.isJavaIdentifierStart(c); } else { if (c == '.') { firstCharacter = true; } else { valid = Character.isJavaIdentifierPart(c); } } } return valid && firstCharacter == false; } private final String _constant; private int _index; private int _endIndex; private Set _classNames = new LinkedHashSet(); private boolean _valid = true; ClassNameExtractor(UTF8Constant constant) { _constant = constant.getString(); _endIndex = _constant.length(); } Set extract() { if (getCurrentCharacter() == '<') { int ddIndex = _constant.indexOf("::", _index); if (ddIndex > 0) { _index = ddIndex + 2; parseTypes(false); if (getCurrentCharacter() == '>') { _index++; } else { setInvalid(); } } else { setInvalid(); } } if (getCurrentCharacter() == '(') { int endIndex = _constant.indexOf(')', _index); if (endIndex > 0) { _index++; _endIndex = endIndex; parseTypes(false); _index = endIndex + 1; _endIndex = _constant.length(); } else { setInvalid(); } } if (_valid) { int numberOfTypes = parseTypes(false); if (numberOfTypes == 0) { setInvalid(); } } return _valid ? _classNames : Collections.EMPTY_SET; } private int parseTypes(boolean generics) { int numberOfTypes = 0; while (_valid && endOfTypes() == false) { parseType(generics); numberOfTypes++; } return numberOfTypes; } private char getCurrentCharacter() { return _index < _endIndex ? _constant.charAt(_index) : 0; } private void setInvalid() { _valid = false; } private boolean endOfTypes() { return _index >= _endIndex || _constant.charAt(_index) == '>'; } private void parseType(boolean generics) { if (generics) { char currentCharacter = getCurrentCharacter(); if (currentCharacter == '+') { _index++; } else if (currentCharacter == '*') { _index++; return; } } boolean arrayType = false; for (; getCurrentCharacter() == '['; _index++) { arrayType = true; } if (arrayType && endOfTypes()) { setInvalid(); } else { char c = getCurrentCharacter(); _index++; if (c == 'L') { parseComplexType(); } else if (c == 'T') { int index = _constant.indexOf(';', _index); if (index < 0) { setInvalid(); } else { _index = index + 1; } } else if ("BCDFIJSVZ".indexOf(c) < 0) { setInvalid(); } } } private void parseComplexType() { int typeIndex = _constant.indexOf('<', _index); int endIndex = _constant.indexOf(';', _index); if (typeIndex >= 0 && typeIndex < endIndex) { extractClassName(typeIndex); parseTypes(true); _index += 2; } else if (endIndex > 0) { extractClassName(endIndex); } else { setInvalid(); } } private void extractClassName(int endIndex) { String className = _constant.substring(_index, endIndex); className = className.replace('/', '.'); _classNames.add(className); _index = endIndex + 1; if (isValid(className) == false) { setInvalid(); } } } �����������������������������������������������������������������������������������������classycle-1.4/src/classycle/CommandLine.java��������������������������������������������������������0000664�0000000�0000000�00000012120�12021221155�0021125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import classycle.util.AndStringPattern; import classycle.util.NotStringPattern; import classycle.util.StringPattern; import classycle.util.StringPatternSequence; import classycle.util.TrueStringPattern; import classycle.util.WildCardPattern; /** * @author Franz-Josef Elmer */ public abstract class CommandLine { private static final String MERGE_INNER_CLASSES = "-mergeInnerClasses"; private static final String INCLUDING_CLASSES = "-includingClasses="; private static final String EXCLUDING_CLASSES = "-excludingClasses="; private static final String REFLECTION_PATTERN = "-reflectionPattern="; private boolean _mergeInnerClasses; protected boolean _valid = true; protected StringPatternSequence _pattern = new AndStringPattern(); protected StringPattern _reflectionPattern; protected String[] _classFiles; public CommandLine(String[] args) { int index = 0; for (;index < args.length && args[index].charAt(0) == '-'; index++) { handleOption(args[index]); } _classFiles = new String[args.length - index]; System.arraycopy(args, index, _classFiles, 0, _classFiles.length); if (_classFiles.length == 0) { _valid = false; } } protected void handleOption(String argument) { if (argument.startsWith(MERGE_INNER_CLASSES)) { _mergeInnerClasses = true; } else if (argument.startsWith(INCLUDING_CLASSES)) { String patterns = argument.substring(INCLUDING_CLASSES.length()); _pattern.appendPattern(WildCardPattern.createFromsPatterns(patterns, ",")); } else if (argument.startsWith(EXCLUDING_CLASSES)) { String patterns = argument.substring(EXCLUDING_CLASSES.length()); StringPattern p = WildCardPattern.createFromsPatterns(patterns, ","); _pattern.appendPattern(new NotStringPattern(p)); } else if (argument.startsWith(REFLECTION_PATTERN)) { String patterns = argument.substring(REFLECTION_PATTERN.length()); if (patterns.length() == 0) { _reflectionPattern = new TrueStringPattern(); } else { _reflectionPattern = WildCardPattern.createFromsPatterns(patterns, ","); } } else { _valid = false; } } /** * Returns all class file descriptors (i.e., class files, directorys, * jar files, or zip files). */ public String[] getClassFiles() { return _classFiles; } /** * Returns the pattern fully qualified class names have to match. The * pattern is based on the options <tt>-includingClasses</tt> and * <tt>-excludingClasses</tt>. If <tt>-includingClasses</tt> is missing * every classes is included which is not excluded. * If <tt>-excludingClasses</tt> is missing no class is excluded. */ public StringPattern getPattern() { return _pattern; } /** * Returns the reflection pattern as extracted from the option * <tt>-reflectionPattern</tt>. */ public StringPattern getReflectionPattern() { return _reflectionPattern; } /** * Returns <tt>true</tt> if the command line arguments and options are * valid. */ public boolean isValid() { return _valid; } /** * Returns <code>true</code> if the command line option * <code>-mergeInnerClasses</code> occured. */ public boolean isMergeInnerClasses() { return _mergeInnerClasses; } /** Returns the usage of correct command line arguments and options. */ public String getUsage() { return "[" + MERGE_INNER_CLASSES + "] " + "[" + INCLUDING_CLASSES + "<pattern1>,<pattern2>,...] " + "[" + EXCLUDING_CLASSES + "<pattern1>,<pattern2>,...] " + "[" + REFLECTION_PATTERN + "<pattern1>,<pattern2>,...] " + "<class files, zip/jar/war/ear files, or folders>"; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/GraphBuilder.java�������������������������������������������������������0000664�0000000�0000000�00000011062�12021221155�0021313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import classycle.graph.AtomicVertex; class GraphBuilder { /** * Creates a graph from the bunch of unresolved nodes. * @param unresolvedNodes All nodes with unresolved references. * @param mergeInnerClasses Merge inner class nodes with their outer class * if <code>true</code>. * @return an array of length <tt>unresolvedNodes.size()</tt> with all * unresolved nodes transformed into <tt>Node</tt> objects * with appropriated links. External nodes are created and linked * but not added to the result array. */ static AtomicVertex[] createGraph(UnresolvedNode[] unresolvedNodes, boolean mergeInnerClasses) { Arrays.sort(unresolvedNodes); Map vertices = createVertices(unresolvedNodes, mergeInnerClasses); AtomicVertex[] result = (AtomicVertex[]) vertices.values().toArray(new AtomicVertex[0]); // Add arces to vertices for (int i = 0; i < unresolvedNodes.length; i++) { UnresolvedNode node = unresolvedNodes[i]; String name = normalize(node.getAttributes().getName(), mergeInnerClasses); AtomicVertex vertex = (AtomicVertex) vertices.get(name); for (Iterator iterator = node.linkIterator(); iterator.hasNext();) { name = normalize((String) iterator.next(), mergeInnerClasses); AtomicVertex head = (AtomicVertex) vertices.get(name); if (head == null) { head = new AtomicVertex(ClassAttributes.createUnknownClass(name, 0)); vertices.put(name, head); } if (vertex != head) { vertex.addOutgoingArcTo(head); } } } return result; } private static Map createVertices(UnresolvedNode[] unresolvedNodes, boolean mergeInnerClasses) { Map vertices = new HashMap(); for (int i = 0; i < unresolvedNodes.length; i++) { ClassAttributes attributes = unresolvedNodes[i].getAttributes(); String type = attributes.getType(); String originalName = attributes.getName(); int size = attributes.getSize(); String name = normalize(originalName, mergeInnerClasses); AtomicVertex vertex = (AtomicVertex) vertices.get(name); if (vertex != null) { ClassAttributes vertexAttributes = (ClassAttributes) vertex.getAttributes(); size += vertexAttributes.getSize(); if (name.equals(originalName) == false) { type = vertexAttributes.getType(); } attributes.addSourcesOf(vertexAttributes); } ClassAttributes newAttributes = new ClassAttributes(name, null, type, size); newAttributes.addSourcesOf(attributes); vertex = new AtomicVertex(newAttributes); vertices.put(name, vertex); } return vertices; } private static String normalize(String name, boolean mergeInnerClasses) { if (mergeInnerClasses) { int index = name.indexOf('$'); if (index >= 0) { name = name.substring(0, index); } } return name; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/NameAndSourceAttributes.java��������������������������������������������0000664�0000000�0000000�00000005261�12021221155�0023502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import classycle.graph.Attributes; import classycle.graph.NameAttributes; /** * Abstract super class of {@link Attributes} with a name and a set of sources. * * @author Franz-Josef Elmer */ public abstract class NameAndSourceAttributes extends NameAttributes { private final Set _sources = new TreeSet(); /** * Creates an instance for the specified name. Initially there are no * sources. */ public NameAndSourceAttributes(String name) { super(name); } /** * Adds the specified source. */ protected void addSource(String source) { _sources.add(source); } /** * Adds the source of the specified attributes. */ protected void addSourcesOf(NameAndSourceAttributes attributes) { _sources.addAll(attributes._sources); } /** * Returns a comma separated list of sources. */ public String getSources() { StringBuffer buffer = new StringBuffer(); for (Iterator iterator = _sources.iterator(); iterator.hasNext();) { String source = (String) iterator.next(); if (source.length() > 0) { if (buffer.length() > 0) { buffer.append(", "); } buffer.append(source); } } return buffer.toString(); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/PackageAttributes.java��������������������������������������������������0000664�0000000�0000000�00000004064�12021221155�0022351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.util.ArrayList; import java.util.List; /** * @author Franz-Josef Elmer */ public class PackageAttributes extends NameAndSourceAttributes { private final List _classes = new ArrayList(); public PackageAttributes(String name) { super(name); } public int getSize() { return _classes.size(); } public String[] getClasses() { return (String[]) _classes.toArray(new String[_classes.size()]); } public void addClass(ClassAttributes classAttributes) { String className = classAttributes.getName(); if (_classes.contains(className) == false) { _classes.add(className); } addSourcesOf(classAttributes); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/PackageProcessor.java���������������������������������������������������0000664�0000000�0000000�00000010677�12021221155�0022211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import classycle.graph.AtomicVertex; import classycle.graph.GraphProcessor; import classycle.graph.Vertex; /** * Processor which extracts the package dependency graph from the class * dependency graph. * * @author Franz-Josef Elmer */ public class PackageProcessor extends GraphProcessor { private static final class Arc { final AtomicVertex tail; final AtomicVertex head; final boolean internalHeadClass; Arc(AtomicVertex tail, AtomicVertex head, boolean internalHeadClass) { this.tail = tail; this.head = head; this.internalHeadClass = internalHeadClass; } void create() { if (internalHeadClass || head.isGraphVertex() == false) { tail.addOutgoingArcTo(head); } } } private final HashMap _packageVertices = new HashMap(); private final List _arcs = new ArrayList(); private AtomicVertex[] _packageGraph; /** * Returns the package graph after processing. * @return can be <tt>null</tt> before processing. */ public AtomicVertex[] getGraph() { return _packageGraph; } protected void initializeProcessing(Vertex[] graph) { _packageVertices.clear(); } protected void processBefore(Vertex vertex) { } protected void processArc(Vertex tail, Vertex head) { PackageVertex tailPackage = getPackageVertex(tail); PackageVertex headPackage = getPackageVertex(head); boolean internalHeadClass = ((AtomicVertex) head).isGraphVertex(); _arcs.add(new Arc(tailPackage, headPackage, internalHeadClass)); } private PackageVertex getPackageVertex(Vertex vertex) { ClassAttributes classAttributes = (ClassAttributes) vertex.getAttributes(); String className = (classAttributes).getName(); int index = className.lastIndexOf('.'); String packageName = index < 0 ? "(default package)" : className.substring(0, index); PackageVertex result = (PackageVertex) _packageVertices.get(packageName); if (result == null) { result = new PackageVertex(packageName); _packageVertices.put(packageName, result); } if (isVertexFromGraph(vertex)) { // not an external package result.reset(); } result.addClass(classAttributes); return result; } private boolean isVertexFromGraph(Vertex vertex) { return vertex instanceof AtomicVertex && ((AtomicVertex) vertex).isGraphVertex(); } protected void processAfter(Vertex vertex) { } protected void finishProcessing(Vertex[] graph) { for (int i = 0; i < _arcs.size(); i++) { ((Arc) _arcs.get(i)).create(); } Iterator vertices = _packageVertices.values().iterator(); ArrayList list = new ArrayList(); while (vertices.hasNext()) { AtomicVertex vertex = (AtomicVertex) vertices.next(); if (vertex.isGraphVertex()) { list.add(vertex); } } _packageGraph = (AtomicVertex[]) list.toArray(new AtomicVertex[list.size()]); } } �����������������������������������������������������������������classycle-1.4/src/classycle/PackageVertex.java������������������������������������������������������0000664�0000000�0000000�00000003335�12021221155�0021500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import classycle.graph.AtomicVertex; /** * @author Franz-Josef Elmer */ public class PackageVertex extends AtomicVertex { public PackageVertex(String name) { super(new PackageAttributes(name)); } public void addClass(ClassAttributes classAttributes) { ((PackageAttributes) getAttributes()).addClass(classAttributes); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/Parser.java�������������������������������������������������������������0000664�0000000�0000000�00000030311�12021221155�0020175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.io.DataInputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import classycle.classfile.ClassConstant; import classycle.classfile.Constant; import classycle.classfile.StringConstant; import classycle.classfile.UTF8Constant; import classycle.graph.AtomicVertex; import classycle.util.StringPattern; import classycle.util.TrueStringPattern; /** * Utility methods for parsing class files and creating directed graphs. * The nodes of the graph are classes. The initial vertex of an edge is the * class which uses the class specified by the terminal vertex. * * @author Franz-Josef Elmer */ public class Parser { private static final int ACC_INTERFACE = 0x200, ACC_ABSTRACT = 0x400; private static final String[] ZIP_FILE_TYPES = new String[] {".zip", ".jar", ".war", ".ear"}; /** Private constructor to prohibit instanciation. */ private Parser() { } /** * Reads and parses class files and creates a direct graph. Short-cut of * <tt>readClassFiles(classFiles, new {@link TrueStringPattern}(), * null, false);</tt> */ public static AtomicVertex[] readClassFiles(String[] classFiles) throws IOException { return readClassFiles(classFiles, new TrueStringPattern(), null, false); } /** * Reads the specified class files and creates a directed graph where each * vertex represents a class. The head vertex of an arc is a class which is * used by the tail vertex of the arc. * The elements of <tt>classFiles</tt> are file names (relative to the * working directory) which are interpreted depending on its file type as * <ul> * <li>name of a class file (file type <tt>.class</tt>) * <li>name of a file of type <code>.zip</code>, <code>.jar</code>, * <code>.war</code>, or <code>.ear</code> * containing class file * <li>name of a folder containing class files or zip/jar/war/ear files * </ul> * Folders and zip/jar/war/ear files are searched recursively * for class files. If a folder is specified only the top-level * zip/jar/war/ear files of that folder are analysed. * @param classFiles Array of file names. * @param pattern Pattern fully qualified class names have to match in order * to be added to the graph. Otherwise they count as * 'external'. * @param reflectionPattern Pattern ordinary string constants of a class * file have to fullfill in order to be handled as * class references. In addition they have to be * syntactically valid fully qualified class names. If * <tt>null</tt> ordinary string constants will not be * checked. * @param mergeInnerClasses If <code>true</code> * merge inner classes with its outer class * @return directed graph. */ public static AtomicVertex[] readClassFiles(String[] classFiles, StringPattern pattern, StringPattern reflectionPattern, boolean mergeInnerClasses) throws IOException { ArrayList unresolvedNodes = new ArrayList(); for (int i = 0; i < classFiles.length; i++) { String classFile = classFiles[i]; File file = new File(classFile); if (file.isDirectory()) { analyseClassFile(file, classFile, unresolvedNodes, reflectionPattern); File[] files = file.listFiles(new FileFilter() { public boolean accept(File file) { return isZipFile(file); } }); for (int j = 0; j < files.length; j++) { String source = createSourceName(classFile, files[j].getName()); analyseClassFiles(new ZipFile(files[j].getAbsoluteFile()), source, unresolvedNodes, reflectionPattern); } } else if (file.getName().endsWith(".class")) { analyseClassFile(file, null, unresolvedNodes, reflectionPattern); } else if (isZipFile(file)) { analyseClassFiles(new ZipFile(file.getAbsoluteFile()), classFile, unresolvedNodes, reflectionPattern); } else { throw new IOException(classFile + " is an invalid file."); } } List filteredNodes = new ArrayList(); for (int i = 0, n = unresolvedNodes.size(); i < n; i++) { UnresolvedNode node = (UnresolvedNode) unresolvedNodes.get(i); if (node.isMatchedBy(pattern)) { filteredNodes.add(node); } } UnresolvedNode[] nodes = new UnresolvedNode[filteredNodes.size()]; nodes = (UnresolvedNode[]) filteredNodes.toArray(nodes); return GraphBuilder.createGraph(nodes, mergeInnerClasses); } private static String createSourceName(String classFile, String name) { return classFile + (classFile.endsWith(File.separator) ? name : File.separatorChar + name); } private static boolean isZipFile(File file) { boolean result = false; String name = file.getName(); for (int i = 0; i < ZIP_FILE_TYPES.length; i++) { if (name.endsWith(ZIP_FILE_TYPES[i])) { result = true; break; } } return result; } private static void analyseClassFile(File file, String source, ArrayList unresolvedNodes, StringPattern reflectionPattern) throws IOException { if (file.isDirectory()) { String[] files = file.list(); for (int i = 0; i < files.length; i++) { File child = new File(file, files[i]); if (child.isDirectory() || files[i].endsWith(".class")) { analyseClassFile(child, source, unresolvedNodes, reflectionPattern); } } } else { unresolvedNodes.add(extractNode(file, source, reflectionPattern)); } } private static UnresolvedNode extractNode(File file, String source, StringPattern reflectionPattern) throws IOException { InputStream stream = null; UnresolvedNode result = null; try { stream = new FileInputStream(file); result = Parser.createNode(stream, source, (int) file.length(), reflectionPattern); } finally { try { stream.close(); } catch (IOException e) {} } return result; } private static void analyseClassFiles(ZipFile zipFile, String source, ArrayList unresolvedNodes, StringPattern reflectionPattern) throws IOException { Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); if (!entry.isDirectory() && entry.getName().endsWith(".class")) { InputStream stream = zipFile.getInputStream(entry); int size = (int) entry.getSize(); unresolvedNodes.add(Parser.createNode(stream, source, size, reflectionPattern)); } } } /** * Creates a new node with unresolved references. * @param stream A just opended byte stream of a class file. * If this method finishes succefully the internal pointer of the * stream will point onto the superclass index. * @param source Optional source of the class file. Can be <code>null</code>. * @param size Number of bytes of the class file. * @param reflectionPattern Pattern used to check whether a * {@link StringConstant} refer to a class. Can be <tt>null</tt>. * @return a node with unresolved link of all classes used by the analysed * class. */ private static UnresolvedNode createNode(InputStream stream, String source, int size, StringPattern reflectionPattern) throws IOException { // Reads constant pool, accessFlags, and class name DataInputStream dataStream = new DataInputStream(stream); Constant[] pool = Constant.extractConstantPool(dataStream); int accessFlags = dataStream.readUnsignedShort(); String name = ((ClassConstant) pool[dataStream.readUnsignedShort()]).getName(); ClassAttributes attributes = null; if ((accessFlags & ACC_INTERFACE) != 0) { attributes = ClassAttributes.createInterface(name, source, size); } else { if ((accessFlags & ACC_ABSTRACT) != 0) { attributes = ClassAttributes.createAbstractClass(name, source, size); } else { attributes = ClassAttributes.createClass(name, source, size); } } // Creates a new node with unresolved references UnresolvedNode node = new UnresolvedNode(); node.setAttributes(attributes); for (int i = 0; i < pool.length; i++) { Constant constant = pool[i]; if (constant instanceof ClassConstant) { ClassConstant cc = (ClassConstant) constant; if (!cc.getName().startsWith(("[")) && !cc.getName().equals(name)) { node.addLinkTo(cc.getName()); } } else if (constant instanceof UTF8Constant) { parseUTF8Constant((UTF8Constant) constant, node, name); } else if (reflectionPattern != null && constant instanceof StringConstant) { String str = ((StringConstant) constant).getString(); if (ClassNameExtractor.isValid(str) && reflectionPattern.matches(str)) { node.addLinkTo(str); } } } return node; } /** * Parses an UFT8Constant and picks class names if it has the correct syntax * of a field or method descirptor. */ static void parseUTF8Constant(UTF8Constant constant, UnresolvedNode node, String className) { Set classNames = new ClassNameExtractor(constant).extract(); for (Iterator iter = classNames.iterator(); iter.hasNext();) { String element = (String) iter.next(); if (className.equals(element) == false) { node.addLinkTo(element); } } } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/UnresolvedNode.java�����������������������������������������������������0000664�0000000�0000000�00000005166�12021221155�0021707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import classycle.util.StringPattern; /** * Class representing a node without resolved links. * * @author Franz-Josef Elmer */ class UnresolvedNode implements Comparable { private ClassAttributes _attributes; private List _nodes = new ArrayList(); void setAttributes(ClassAttributes attributes) { _attributes = attributes; } ClassAttributes getAttributes() { return _attributes; } void addLinkTo(String node) { _nodes.add(node); } Iterator linkIterator() { return new Iterator() { private int _index; public void remove() { throw new UnsupportedOperationException(); } public boolean hasNext() { return _index < _nodes.size(); } public Object next() { return hasNext() ? _nodes.get(_index++) : null; } }; } public int compareTo(Object obj) { return getAttributes().getName().compareTo( ((UnresolvedNode) obj).getAttributes().getName()); } public boolean isMatchedBy(StringPattern pattern) { return pattern.matches(getAttributes().getName()); } }����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/XMLPackageRenderer.java�������������������������������������������������0000664�0000000�0000000�00000004231�12021221155�0022346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import classycle.renderer.AtomicVertexRenderer; import classycle.renderer.TemplateBasedClassRenderer; import classycle.renderer.XMLAtomicVertexRenderer; /** * XML renderer of an {@link AtomicVertex} with * {@link NameAttributes}. * * @author Franz-Josef Elmer */ public class XMLPackageRenderer extends XMLAtomicVertexRenderer { protected String getElement() { return "package"; } protected String getRefElement() { return "packageRef"; } protected AtomicVertexRenderer getVertexRenderer() { return new TemplateBasedClassRenderer(" <" + getElement() + " name=\"{0}\" sources=\"{9}\" size=\"{2}\" usedBy=\"{4}\"" + " usesInternal=\"{5}\" usesExternal=\"{6}\" layer=\"{7}\"" + " cycle=\"{8}\">\n"); } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/XMLPackageStrongComponentRenderer.java����������������������������������0000664�0000000�0000000�00000003741�12021221155�0025433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle; import classycle.renderer.XMLStrongComponentRenderer; /** * @author Franz-Josef Elmer */ public class XMLPackageStrongComponentRenderer extends XMLStrongComponentRenderer { public XMLPackageStrongComponentRenderer(int minimumSize) { super(minimumSize); } protected String getNodesElementName() { return "packages"; } protected String getNodeElementName() { return "packageRef"; } protected String getCenterNodesElementName() { return "centerPackages"; } protected String getStrongComponentElementName() { return "packageCycle"; } } �������������������������������classycle-1.4/src/classycle/ant/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0016662�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/ant/ClassycleTask.java��������������������������������������������������0000664�0000000�0000000�00000010610�12021221155�0022270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.ant; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; import classycle.util.AndStringPattern; import classycle.util.NotStringPattern; import classycle.util.StringPattern; import classycle.util.TrueStringPattern; import classycle.util.WildCardPattern; /** * Common attributes of all Classyle Ant tasks. * * @author Franz-Josef Elmer */ public abstract class ClassycleTask extends Task { private boolean _mergeInnerClasses; private StringPattern _includingClasses = new TrueStringPattern(); private StringPattern _excludingClasses = new TrueStringPattern(); private StringPattern _reflectionPattern; private LinkedList _fileSets = new LinkedList(); protected File _reportFile; public void setMergeInnerClasses(boolean mergeInnerClasses) { _mergeInnerClasses = mergeInnerClasses; } public void setIncludingClasses(String patternList) { _includingClasses = WildCardPattern.createFromsPatterns(patternList, ", "); } public void setExcludingClasses(String patternList) { _excludingClasses = new NotStringPattern( WildCardPattern.createFromsPatterns(patternList, ", ")); } public void setReflectionPattern(String patternList) { if ("".equals(patternList)) { _reflectionPattern = new TrueStringPattern(); } else { _reflectionPattern = WildCardPattern.createFromsPatterns(patternList, ", "); } } public void addConfiguredFileset(FileSet set) { _fileSets.add(set); } public void execute() throws BuildException { super.execute(); if (_fileSets.size() == 0) { throw new BuildException("at least one file set is required"); } } protected String[] getClassFileNames() { ArrayList fileNames = new ArrayList(); String fileSeparator = System.getProperty("file.separator"); for (Iterator i = _fileSets.iterator(); i.hasNext();) { FileSet set = (FileSet) i.next(); DirectoryScanner scanner = set.getDirectoryScanner(getProject()); String path = scanner.getBasedir().getAbsolutePath(); String[] localFiles = scanner.getIncludedFiles(); for (int j = 0; j < localFiles.length; j++) { fileNames.add(path + fileSeparator + localFiles[j]); } } String[] classFiles = new String[fileNames.size()]; return (String[]) fileNames.toArray(classFiles); } protected StringPattern getPattern() { AndStringPattern pattern = new AndStringPattern(); pattern.appendPattern(_includingClasses); pattern.appendPattern(_excludingClasses); return pattern; } protected StringPattern getReflectionPattern() { return _reflectionPattern; } protected boolean isMergeInnerClasses() { return _mergeInnerClasses; } public void setReportFile(File xmlFile) { _reportFile = xmlFile; } } ������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/ant/DependencyCheckingTask.java�����������������������������������������0000664�0000000�0000000�00000017013�12021221155�0024064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.ant; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import org.apache.tools.ant.BuildException; import classycle.Analyser; import classycle.dependency.DefaultResultRenderer; import classycle.dependency.DependencyChecker; import classycle.dependency.ResultRenderer; import classycle.util.Text; /** * Ant Task for checking class dependencies. * <p> * <table border="1" cellpadding="5" cellspacing="0"> * <tr><th>Attribute</th><th>Description</th><th>Required</th></tr> * <tr><td valign="top">includingClasses</td> * <td>Comma or space separated list of wild-card patterns of * fully-qualified class name which are included in the analysis. * Only '*' are recognized as wild-card character. * </td> * <td valign="top">No. By default all classes defined in the file set * are included. * </td> * </tr> * <tr><td valign="top">excludingClasses</td> * <td valign="top">Comma or space separated list of wild-card patterns of * fully-qualified class name which are excluded from the analysis. * Only '*' are recognized as wild-card character. * </td> * <td valign="top">No. By default no class defined in the file set is * excluded. * </td> * </tr> * <tr><td valign="top">mergeInnerClasses</td> * <td valign="top">If <code>true</code> all class vertices are merged * with the vertices of the corresponding inner classes. * </td> * <td valign="top">No. Default is <tt>false</tt>.</td> * </tr> * <tr><td valign="top">reflectionPattern</td> * <td valign="top">Comma or space separated list of wild-card patterns of * fully-qualified class name. * Only '*' are recognized as wild-card character. * <p> * If in the code of a class an ordinary string constant matches * one of these patterns and if this string constant * has a valid syntax for a fully-qualified * class name this constant will be treated as a class reference. * </td> * <td valign="top">No. By default ordinary string constants are not * treated as class references. * </td> * </tr> * <tr><td valign="top">definitionFile</td> * <td valign="top">Path of the dependency definition file. * It is either absolute or relative to the base directory. * </td> * <td valign="top">No. By default the dependency definition commands * are embedded in the ant task. * </td> * </tr> * <tr><td valign="top">failOnUnwantedDependencies</td> * <td valign="top">If <tt>true</tt> the task will fail if an * unwanted dependency is found. * </td> * <td valign="top">No. Default value is <tt>false</tt>. * </td> * </tr> * <tr><td valign="top">reportFile</td> * <td valign="top">Path of the report file. * It is either absolute or relative to the base directory.</td> * <td valign="top">No. By default the result is written onto the console.</td> * <tr><td valign="top">resultRenderer</td> * <td valign="top">Fully-qualified class name of a * {@link ResultRenderer}. * </td> * <td valign="top">No. By default {@link DefaultResultRenderer} is used. * </td> * </tr> * </table> * * @author Franz-Josef Elmer */ public class DependencyCheckingTask extends ClassycleTask { private File _definitionFile; private String _dependencyDefinition; private String _resultRenderer; private boolean _failOnUnwantedDependencies; public void setFailOnUnwantedDependencies(boolean failOnUnwantedDependencies) { _failOnUnwantedDependencies = failOnUnwantedDependencies; } public void setDefinitionFile(File definitionFile) { _definitionFile = definitionFile; } public void setResultRenderer(String resultRenderer) { _resultRenderer = resultRenderer; } public void addText(String text) { _dependencyDefinition = text.trim(); } public void execute() throws BuildException { super.execute(); boolean ok = false; PrintWriter printWriter = null; try { Analyser analyser = new Analyser(getClassFileNames(), getPattern(), getReflectionPattern(), isMergeInnerClasses()); Map properties = _definitionFile == null ? getProject().getProperties() : System.getProperties(); DependencyChecker dependencyChecker = new DependencyChecker(analyser, getDependencyDefinitions(), properties, getRenderer()); printWriter = _reportFile == null ? new PrintWriter(System.out) : new PrintWriter(new FileWriter(_reportFile)); ok = dependencyChecker.check(printWriter); printWriter.flush(); printWriter.close(); } catch (BuildException e) { throw e; } catch (Exception e) { throw new BuildException(e); } finally { if (printWriter != null) { printWriter.close(); } } if (_failOnUnwantedDependencies && ok == false) { throw new BuildException( "Unwanted dependencies found. See output for details."); } } private ResultRenderer getRenderer() throws InstantiationException, IllegalAccessException, ClassNotFoundException { ResultRenderer renderer = new DefaultResultRenderer(); if (_resultRenderer != null) { renderer = (ResultRenderer) Class.forName(_resultRenderer).newInstance(); } return renderer; } private String getDependencyDefinitions() throws IOException, BuildException { String result = _dependencyDefinition;; if (_definitionFile != null) { result = Text.readTextFile(_definitionFile); } if (result.length() == 0) { throw new BuildException("Empty dependency definition."); } return result; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/ant/ReportTask.java�����������������������������������������������������0000664�0000000�0000000�00000014177�12021221155�0021635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.ant; import java.io.FileWriter; import java.io.PrintWriter; import java.util.HashSet; import org.apache.tools.ant.BuildException; import classycle.Analyser; /** * Ant Task for creating a Classycle Analyser report, either raw, CSV, or XML. * <p> * <table border="1" cellpadding="5" cellspacing="0"> * <tr><th>Attribute</th><th>Description</th><th>Required</th></tr> * <tr><td valign="top">reportFile</td> * <td valign="top">Path of the report file. * It is either absolute or relative to the base directory.</td> * <td valign="top">Yes</td> * <tr><td valign="top">reportType</td> * <td valign="top">Type of the report. Has to be either <tt>raw</tt>, * <tt>csv</tt>, or <tt>xml</tt>.</td> * <td valign="top">No. Default is <tt>xml</tt></td> * </tr> * <tr><td valign="top">title</td> * <td valign="top">Title of the XML report.</td> * <td valign="top">No. Default is the first file in the file set.</td> * </tr> * <tr><td valign="top">packagesOnly</td> * <td valign="top">If <tt>true</tt> only packages and their dependencies * are analysed and reported (only in XML report).</td> * <td valign="top">No. Default is <tt>false</tt>.</td> * </tr> * <tr><td valign="top">includingClasses</td> * <td>Comma or space separated list of wild-card patterns of * fully-qualified class name which are included in the analysis. * Only '*' are recognized as wild-card character. * </td> * <td valign="top">No. By default all classes defined in the file set * are included. * </td> * </tr> * <tr><td valign="top">excludingClasses</td> * <td valign="top">Comma or space separated list of wild-card patterns of * fully-qualified class name which are excluded from the analysis. * Only '*' are recognized as wild-card character. * </td> * <td valign="top">No. By default no class defined in the file set is * excluded. * </td> * </tr> * <tr><td valign="top">mergeInnerClasses</td> * <td valign="top">If <code>true</code> all class vertices are merged * with the vertices of the corresponding inner classes. * </td> * <td valign="top">No. Default is <tt>false</tt>.</td> * </tr> * <tr><td valign="top">reflectionPattern</td> * <td valign="top">Comma or space separated list of wild-card patterns of * fully-qualified class name. * Only '*' are recognized as wild-card character. * <p> * If in the code of a class an ordinary string constant matches * one of these patterns and if this string constant * has a valid syntax for a fully-qualified * class name this constant will be treated as a class reference. * </td> * <td valign="top">No. By default ordinary string constants are not * treated as class references. * </td> * </tr> * </table> * * @author Boris Gruschko * @author Franz-Josef Elmer */ public class ReportTask extends ClassycleTask { public static final String TYPE_RAW = "raw", TYPE_CSV = "csv", TYPE_XML = "xml"; private static final HashSet TYPES = new HashSet(); static { TYPES.add(TYPE_RAW); TYPES.add(TYPE_CSV); TYPES.add(TYPE_XML); } private boolean _packagesOnly; private String _reportType = TYPE_XML; private String _title; public void setPackagesOnly(boolean packagesOnly) { _packagesOnly = packagesOnly; } public void setReportType(String csvFile) { _reportType = csvFile; } public void setTitle(String title) { _title = title; } public void execute() throws BuildException { super.execute(); if (!TYPES.contains(_reportType)) { throw new BuildException("invalid attribute 'reportType': " + _reportType); } if (_reportFile == null) { throw new BuildException("missing attribute 'reportFile'."); } String[] classFiles = getClassFileNames(); if (classFiles.length > 0 && _title == null) { _title = classFiles[0]; } Analyser analyser = new Analyser(classFiles, getPattern(), getReflectionPattern(), isMergeInnerClasses()); try { analyser.readAndAnalyse(_packagesOnly); PrintWriter writer = new PrintWriter(new FileWriter(_reportFile)); if (_reportType.equals(TYPE_XML)) { analyser.printXML(_title, _packagesOnly, writer); } else if (_reportType.equals(TYPE_CSV)) { analyser.printCSV(writer); } else if (_reportType.equals(TYPE_RAW)) { analyser.printRaw(writer); } } catch (Exception e) { throw new BuildException(e); } } }�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/��������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0020045�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/ClassConstant.java��������������������������������������������0000664�0000000�0000000�00000005334�12021221155�0023474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Class constant. Refers to an instance of {@link UTF8Constant} which * holds the fully qualifies class name. * * @author Franz-Josef Elmer */ public class ClassConstant extends Constant { private final int _nameIndex; /** * Creates an instance for the specified index refering an * {@link UTF8Constant}. * @param pool Pool of all {@link Constant Constants}. * @param nameIndex Index into <tt>pool</tt>. */ public ClassConstant(Constant[] pool, int nameIndex) { super(pool); _nameIndex = nameIndex; } /** * Returns the fully-qualified class name. In the case of an object array * only the class name of the object is returned. * @return fully-qualified class name in standard notation with '.'. */ public String getName() { String result = null; Constant c = getConstant(_nameIndex); if (c instanceof UTF8Constant) { result = ((UTF8Constant) c).getString().replace('/', '.'); if (result.startsWith("[")) { // An array class: Extract class name int index = result.indexOf('L'); if (index > 0) { result = result.substring(index + 1, result.length() - 1); } } } return result; } /** Returns the constant type and the class name. */ public String toString() { return "CONSTANT_Class: " + getName(); } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/Constant.java�������������������������������������������������0000664�0000000�0000000�00000012222�12021221155�0022500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; import java.io.DataInputStream; import java.io.IOException; /** * Abstract super class of all type of constants in the constant pool of * a class file. * * @author Franz-Josef Elmer */ public abstract class Constant { private static final int MAGIC = 0xcafebabe; private static final int CONSTANT_CLASS = 7, CONSTANT_FIELDREF = 9, CONSTANT_METHODREF = 10, CONSTANT_INTERFACE_METHODREF = 11, CONSTANT_STRING = 8, CONSTANT_INTEGER = 3, CONSTANT_FLOAT = 4, CONSTANT_LONG = 5, CONSTANT_DOUBLE = 6, CONSTANT_NAME_AND_TYPE = 12, CONSTANT_UTF8 = 1; /** * Extracts the constant pool from the specified data stream of a class file. * @param stream Input stream of a class file starting at the first byte. * @return extracted array of constants. * @throws IOException in case of reading errors or invalid class file. */ public static Constant[] extractConstantPool(DataInputStream stream) throws IOException { Constant[] pool = null; if (stream.readInt() == MAGIC) { stream.readUnsignedShort(); stream.readUnsignedShort(); pool = new Constant[stream.readUnsignedShort()]; for (int i = 1; i < pool.length; ) { boolean skipIndex = false; Constant c = null; int type = stream.readUnsignedByte(); switch (type) { case CONSTANT_CLASS: c = new ClassConstant(pool, stream.readUnsignedShort()); break; case CONSTANT_FIELDREF: c = new FieldRefConstant(pool, stream.readUnsignedShort(), stream.readUnsignedShort()); break; case CONSTANT_METHODREF: c = new MethodRefConstant(pool, stream.readUnsignedShort(), stream.readUnsignedShort()); break; case CONSTANT_INTERFACE_METHODREF: c = new InterfaceMethodRefConstant(pool, stream.readUnsignedShort(), stream.readUnsignedShort()); break; case CONSTANT_STRING: c = new StringConstant(pool, stream.readUnsignedShort()); break; case CONSTANT_INTEGER: c = new IntConstant(pool, stream.readInt()); break; case CONSTANT_FLOAT: c = new FloatConstant(pool, stream.readFloat()); break; case CONSTANT_LONG: c = new LongConstant(pool, stream.readLong()); skipIndex = true; break; case CONSTANT_DOUBLE: c = new DoubleConstant(pool, stream.readDouble()); skipIndex = true; break; case CONSTANT_NAME_AND_TYPE: c = new NameAndTypeConstant(pool, stream.readUnsignedShort(), stream.readUnsignedShort()); break; case CONSTANT_UTF8: c = new UTF8Constant(pool, stream.readUTF()); break; } pool[i] = c; i += skipIndex ? 2 : 1; // double and long constants occupy two entries } return pool; } throw new IOException("Not a class file: Magic number missing."); } private Constant[] _pool; /** * Creates an instance. * @param pool The poole which will be needed to resolve references. */ public Constant(Constant[] pool) { _pool = pool; } /** * Returns the specified constant from the pool. * @param index Index of requested constant. */ public Constant getConstant(int index) { return _pool[index]; } } //class������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/ConstantPoolPrinter.java��������������������������������������0000664�0000000�0000000�00000005201�12021221155�0024675�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; /** * Application which prints the {@link Constant} pool of a class file onto the * console. * * @author Franz-Josef Elmer */ public class ConstantPoolPrinter { /** * Reads a class file and prints the constant pool onto <tt>System.out</tt>. * @param args File name of the class file in <tt>args[0]</tt> */ public static void main(String[] args) { if (args.length == 0) { System.out.println( "Usage: java classycle.classfile.ConstantPoolPrinter <class files>"); } for (int i = 0; i < args.length; i++) { investigate(args[i]); } } private static void investigate(String fileName) { DataInputStream stream = null; try { stream = new DataInputStream(new FileInputStream(fileName)); Constant[] pool = Constant.extractConstantPool(stream); printConstantPool(pool); } catch (IOException e) { System.out.println(e); } finally { try { stream.close(); } catch (IOException e) { } } } private static void printConstantPool(Constant[] pool) { for (int i = 0; i < pool.length; i++) { System.out.println(i + ": " + pool[i]); } } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/DoubleConstant.java�������������������������������������������0000664�0000000�0000000�00000003701�12021221155�0023635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant representing a <tt>double</tt> value. * * @author Franz-Josef Elmer */ public class DoubleConstant extends Constant { private final double _value; /** Creates an instance for the specified double value. */ public DoubleConstant(Constant[] pool, double value) { super(pool); _value = value; } /** Returns the wrapped double value. */ public double getValue() { return _value; } /** Returns the constant type and the double value. */ public String toString() { return "CONSTANT_Double: " + _value; } } //class���������������������������������������������������������������classycle-1.4/src/classycle/classfile/FieldRefConstant.java�����������������������������������������0000664�0000000�0000000�00000003511�12021221155�0024102�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Reference constant for a field. * * @author Franz-Josef Elmer */ public class FieldRefConstant extends RefConstant { public FieldRefConstant(Constant[] pool, int classIndex, int nameAndTypeIndex) { super(pool, classIndex, nameAndTypeIndex); } /** Returns constant type, class name, field name, and descriptor. */ public String toString() { return toString("CONSTANT_FieldRef"); } } //class���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/FloatConstant.java��������������������������������������������0000664�0000000�0000000�00000003667�12021221155�0023503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant representing a <tt>float</tt> value. * * @author Franz-Josef Elmer */ public class FloatConstant extends Constant { private final float _value; /** Creates an instance for the specified float value. */ public FloatConstant(Constant[] pool, float value) { super(pool); _value = value; } /** Returns the wrapped float value. */ public float getValue() { return _value; } /** Returns the constant type and the float value. */ public String toString() { return "CONSTANT_Float: " + _value; } } //class�������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/IntConstant.java����������������������������������������������0000664�0000000�0000000�00000003647�12021221155�0023166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant representing a <tt>int</tt> value. * * @author Franz-Josef Elmer */ public class IntConstant extends Constant { private final int _value; /** Creates an instance for the specified int value. */ public IntConstant(Constant[] pool, int value) { super(pool); _value = value; } /** Returns the wrapped int value. */ public int getValue() { return _value; } /** Returns the constant type and the int value. */ public String toString() { return "CONSTANT_Integer: " + _value; } } //class�����������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/InterfaceMethodRefConstant.java�������������������������������0000664�0000000�0000000�00000003575�12021221155�0026132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Reference constant for an interface method. * * @author Franz-Josef Elmer */ public class InterfaceMethodRefConstant extends RefConstant { public InterfaceMethodRefConstant(Constant[] pool, int classIndex, int nameAndTypeIndex) { super(pool, classIndex, nameAndTypeIndex); } /** Returns constant type, class name, method name, and descriptor. */ public String toString() { return toString("CONSTANT_InterfaceMethodRef"); } } //class�����������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/LongConstant.java���������������������������������������������0000664�0000000�0000000�00000003655�12021221155�0023332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant representing a <tt>long</tt> value. * * @author Franz-Josef Elmer */ public class LongConstant extends Constant { private final long _value; /** Creates an instance for the specified long value. */ public LongConstant(Constant[] pool, long value) { super(pool); _value = value; } /** Returns the wrapped long value. */ public long getValue() { return _value; } /** Returns the constant type and the long value. */ public String toString() { return "CONSTANT_Long: " + _value; } } //class�����������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/MethodRefConstant.java����������������������������������������0000664�0000000�0000000�00000003515�12021221155�0024303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Reference constant for a method. * * @author Franz-Josef Elmer */ public class MethodRefConstant extends RefConstant { public MethodRefConstant(Constant[] pool, int classIndex, int nameAndTypeIndex) { super(pool, classIndex, nameAndTypeIndex); } /** Returns constant type, class name, method name, and descriptor. */ public String toString() { return toString("CONSTANT_MethodRef"); } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/NameAndTypeConstant.java��������������������������������������0000664�0000000�0000000�00000005372�12021221155�0024576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant holding a name and a type or method descriptor. * * @author Franz-Josef Elmer */ public class NameAndTypeConstant extends Constant { private final int _nameIndex; private final int _descriptorIndex; /** * Creates an instance for the specified name and type or method descriptor. * @param pool Constant pool. Needed to resolve references. * @param nameIndex Index of the name in the pool. * @param descriptorIndex Index of the type or method descriptor in the pool. */ public NameAndTypeConstant(Constant[] pool, int nameIndex, int descriptorIndex) { super(pool); _nameIndex = nameIndex; _descriptorIndex = descriptorIndex; } /** Returns the name. */ public String getName() { String result = null; Constant c = getConstant(_nameIndex); if (c instanceof UTF8Constant) { result = ((UTF8Constant) c).getString(); } return result; } /** Returns the type or method descriptor. */ public String getDescriptor() { String result = null; Constant c = getConstant(_descriptorIndex); if (c instanceof UTF8Constant) { result = ((UTF8Constant) c).getString(); } return result; } /** Returns constant type, name, and descriptor. */ public String toString() { return "CONSTANT_NameAndType: " + getName() + ", " + getDescriptor(); } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/RefConstant.java����������������������������������������������0000664�0000000�0000000�00000005262�12021221155�0023143�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Abstract supper class of all reference constants. * * @author Franz-Josef Elmer */ public abstract class RefConstant extends Constant { private final int _classIndex; private final int _nameAndTypeIndex; /** * Creates an instance for the specified class, name, and type. * @param pool Constant pool. Needed for resolving references. * @param classIndex Index of {@link ClassConstant}. * @param nameAndTypeIndex Index of {@link NameAndTypeConstant}. */ public RefConstant(Constant[] pool, int classIndex, int nameAndTypeIndex) { super(pool); _classIndex = classIndex; _nameAndTypeIndex = nameAndTypeIndex; } /** Returns the class constant. */ public ClassConstant getClassConstant() { return (ClassConstant) getConstant(_classIndex); } /** Returns the name-and-type constant. */ public NameAndTypeConstant getNameAndType() { return (NameAndTypeConstant) getConstant(_nameAndTypeIndex); } /** Pretty printing. Will be used by <tt>toString</tt> of the subclasses. */ protected String toString(String constantType) { return constantType + ": Class = " + getClassConstant().getName() + ", Name = " + getNameAndType().getName() + ", Descriptor = " + getNameAndType().getDescriptor(); } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/StringConstant.java�������������������������������������������0000664�0000000�0000000�00000004345�12021221155�0023676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant of a <tt>String</tt> value. * * @author Franz-Josef Elmer */ public class StringConstant extends Constant { private final int _stringIndex; /** * Creates an instance for the specfied index. * @param pool Constant pool. Needed for resolving the reference. * @param stringIndex Index of an {@link UTF8Constant}. */ public StringConstant(Constant[] pool, int stringIndex) { super(pool); _stringIndex = stringIndex; } /** Returns the string value. */ public String getString() { String result = null; Constant c = getConstant(_stringIndex); if (c instanceof UTF8Constant) { result = ((UTF8Constant) c).getString(); } return result; } /** Returns the constant type and the string value. */ public String toString() { return "CONSTANT_String: " + getString(); } } //class�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/classfile/UTF8Constant.java���������������������������������������������0000664�0000000�0000000�00000003775�12021221155�0023164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.classfile; /** * Constant of an arbitrary Unicode string. * * @author Franz-Josef Elmer */ public class UTF8Constant extends Constant { private final String _string; /** * Creates an instance for the specified string. * @param pool Constant pool. * @param string wrapped string. */ public UTF8Constant(Constant[] pool, String string) { super(pool); _string = string; } /** Returns the wrapped string. */ public String getString() { return _string; } /** Returns the constant type and the wrapped string. */ public String toString() { return "CONSTANT_Utf8: " + _string; } } //class���classycle-1.4/src/classycle/dependency/�������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0020216�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/CheckCyclesStatement.java������������������������������������0000664�0000000�0000000�00000007510�12021221155�0025131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Created on 07.04.2006 */ package classycle.dependency; import java.util.ArrayList; import java.util.List; import classycle.PackageProcessor; import classycle.graph.AtomicVertex; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; import classycle.graph.StrongComponentAnalyser; import classycle.graph.Vertex; import classycle.util.StringPattern; public class CheckCyclesStatement implements Statement { private final StringPattern _set; private final int _maximumSize; private final boolean _packageCycles; private final SetDefinitionRepository _repository; public CheckCyclesStatement(StringPattern set, int size, boolean cycles, SetDefinitionRepository repository) { _set = set; _maximumSize = size; _packageCycles = cycles; _repository = repository; } public Result execute(AtomicVertex[] graph) { List filteredGraph = new ArrayList(); for (int i = 0; i < graph.length; i++) { if (_set.matches(((NameAttributes) graph[i].getAttributes()).getName())) { filteredGraph.add(graph[i]); } } graph = (AtomicVertex[]) filteredGraph.toArray(new AtomicVertex[0]); if (_packageCycles) { PackageProcessor processor = new PackageProcessor(); processor.deepSearchFirst(graph); graph = processor.getGraph(); } StrongComponentAnalyser analyser = new StrongComponentAnalyser(graph); Vertex[] condensedGraph = analyser.getCondensedGraph(); CyclesResult result = new CyclesResult(createStatement(), _packageCycles); for (int i = 0; i < condensedGraph.length; i++) { StrongComponent strongComponent = (StrongComponent) condensedGraph[i]; if (strongComponent.getNumberOfVertices() > _maximumSize) { result.addCycle(strongComponent); } } return result; } public String toString() { return createStatement(); } private String createStatement() { StringBuffer buffer = new StringBuffer(); buffer.append(DependencyDefinitionParser.CHECK_KEY_WORD).append(' '); if (_packageCycles) { buffer.append(DependencyDefinitionParser.PACKAGE_CYCLES_KEY_WORD); } else { buffer.append(DependencyDefinitionParser.CLASS_CYCLES_KEY_WORD); } buffer.append(" > ").append(_maximumSize).append(' '); buffer.append(DependencyDefinitionParser.IN_KEY_WORD).append(' '); buffer.append(_repository.toString(_set)); return new String(buffer); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/CheckSetStatement.java���������������������������������������0000664�0000000�0000000�00000005127�12021221155�0024444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Created on 07.04.2006 */ package classycle.dependency; import classycle.graph.AtomicVertex; import classycle.graph.NameAttributes; import classycle.util.StringPattern; public class CheckSetStatement implements Statement { private final StringPattern _set; private final SetDefinitionRepository _repository; public CheckSetStatement(StringPattern set, SetDefinitionRepository repository) { _set = set; _repository = repository; } public Result execute(AtomicVertex[] graph) { int size = 0; for (int i = 0; i < graph.length; i++) { if (_set.matches(((NameAttributes) graph[i].getAttributes()).getName())) { size++; } } StringBuffer buffer = new StringBuffer("Set "); buffer.append(_repository.toString(_set)); if (size == 0) { buffer.append(" is empty."); } else if (size == 1) { buffer.append(" has one class."); } else { buffer.append(" has ").append(size).append(" classes."); } return new TextResult(new String(buffer.append('\n')), size > 0); } public String toString() { return DependencyDefinitionParser.CHECK_KEY_WORD + " set " + _repository.toString(_set); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/CyclesResult.java��������������������������������������������0000664�0000000�0000000�00000007375�12021221155�0023516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Created on 07.04.2006 */ package classycle.dependency; import java.util.ArrayList; import java.util.List; import classycle.graph.AtomicVertex; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; import classycle.renderer.AbstractStrongComponentRenderer; /** * Result of a cyclic check. * * @author Franz-Josef Elmer */ public class CyclesResult implements Result { private final List<StrongComponent> _cycles = new ArrayList<StrongComponent>(); private final String _statement; private final boolean _packageCycle; /** * Creates an instance for the specified statement. * * @param packageCycle If <code>true/false</code> the check is on package/class cycles */ public CyclesResult(String statement, boolean packageCycle) { _statement = statement; _packageCycle = packageCycle; } /** * Adds the specified cycle. */ public void addCycle(StrongComponent cycle) { _cycles.add(cycle); } /** * Returns all added cycles. */ public List<StrongComponent> getCycles() { return _cycles; } /** * Returns the statement. */ public String getStatement() { return _statement; } /** * Returns <code>true/false</code> if this result is on package/class cycles. */ public boolean isPackageCycle() { return _packageCycle; } /** * Returns <code>true</code> if no cycles have been added. */ public boolean isOk() { return _cycles.size() == 0; } /** * Returns the result in a human-readable form which is used by the {@link DefaultResultRenderer}. */ public String toString() { StringBuffer buffer = new StringBuffer(_statement); if (isOk()) { buffer.append("\tOK"); } else { for (StrongComponent component : _cycles) { int numberOfVertices = component.getNumberOfVertices(); buffer.append("\n "); buffer.append(AbstractStrongComponentRenderer.createName(component)); buffer.append(" contains ").append(numberOfVertices); buffer.append(' ').append(_packageCycle ? "packages" : "classes").append(':'); for (int i = 0; i < numberOfVertices; i++) { buffer.append("\n "); AtomicVertex vertex = component.getVertex(i); buffer.append(((NameAttributes) vertex.getAttributes()).getName()); } } } return new String(buffer.append('\n')); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DefaultPreferenceFactory.java��������������������������������0000664�0000000�0000000�00000006627�12021221155�0026007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.HashMap; /** * Factory of {@link Preference Preferences} known by the * {@link DefaultResultRenderer}. * * <table border="1" cellspacing="0" cellpadding="5"> * <tr><th>Preference Key</th><th>Description</th></tr> * <tr><td><tt>onlyShortestPaths</tt></td> * <td>Only the shortest paths are reported in the case of * unwanted dependencies.</td> * </tr> * <tr><td><tt>allPaths</tt></td> * <td>All paths are reported in the case of * unwanted dependencies.</td> * </tr> * <tr><td><tt>onlyFailures</tt></td> * <td>Only results are reported which are not ok.</td> * </tr> * <tr><td><tt>allResults</tt></td> * <td>All results are reported.</td> * </tr> * </table> * @author Franz-Josef Elmer */ public class DefaultPreferenceFactory implements PreferenceFactory { public static final Preference ONLY_SHORTEST_PATHS = new DefaultPreference("onlyShortestPaths"); public static final Preference ALL_PATHS = new DefaultPreference("allPaths"); public static final Preference ALL_RESULTS = new DefaultPreference("allResults"); public static final Preference ONLY_FAILURES = new DefaultPreference("onlyFailures"); private static class DefaultPreference implements Preference { private static final HashMap REPOSITORY = new HashMap(); public static Preference getPreference(String key) { return (Preference) REPOSITORY.get(key); } private final String _key; protected DefaultPreference(String key) { _key = key; if (REPOSITORY.containsKey(key)) { throw new IllegalArgumentException( "There exists already an instance for '" + key + "'."); } REPOSITORY.put(key, this); } public final String getKey() { return _key; } public String toString() { return getKey(); } } public Preference get(String key) { return DefaultPreference.getPreference(key); } } ���������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DefaultResultRenderer.java�����������������������������������0000664�0000000�0000000�00000007301�12021221155�0025334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * @author Franz-Josef Elmer */ public class DefaultResultRenderer extends ResultRenderer { private static final String SHOW = DependencyDefinitionParser.SHOW_KEY_WORD + ' '; private static final PreferenceFactory FACTORY = new DefaultPreferenceFactory(); private static final TextResult ONLY_SHORTEST_PATHS = new TextResult(SHOW + DefaultPreferenceFactory.ONLY_SHORTEST_PATHS.getKey() + '\n'); private static final TextResult ALL_PATHS = new TextResult(SHOW + DefaultPreferenceFactory.ALL_PATHS.getKey() + '\n'); private boolean _allResults; public PreferenceFactory getPreferenceFactory() { return FACTORY; } public void considerPreference(Preference preference) { if (preference == DefaultPreferenceFactory.ONLY_SHORTEST_PATHS) { _shortestPaths = true; } else if (preference == DefaultPreferenceFactory.ALL_PATHS) { _shortestPaths = false; } else if (preference == DefaultPreferenceFactory.ALL_RESULTS) { _allResults = true; } else if (preference == DefaultPreferenceFactory.ONLY_FAILURES) { _allResults = false; } } public Result getDescriptionOfCurrentPreferences() { StringBuffer buffer = new StringBuffer(SHOW); buffer.append(_shortestPaths ? DefaultPreferenceFactory.ONLY_SHORTEST_PATHS.getKey() : DefaultPreferenceFactory.ALL_PATHS.getKey()) .append(' ') .append(_allResults ? DefaultPreferenceFactory.ALL_RESULTS.getKey() : DefaultPreferenceFactory.ONLY_FAILURES.getKey()) .append('\n'); return new TextResult(new String(buffer)); } public String render(Result result) { StringBuffer buffer = new StringBuffer(); render(buffer, result); return new String(buffer); } private void render(StringBuffer buffer, Result result) { if (result instanceof ResultContainer) { ResultContainer results = (ResultContainer) result; for (int i = 0, n = results.getNumberOfResults(); i < n; i++) { render(buffer, results.getResult(i)); } } else if (_allResults || result.isOk() == false) { buffer.append(result.toString()); } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyChecker.java���������������������������������������0000664�0000000�0000000�00000010753�12021221155�0024432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.io.PrintWriter; import java.util.Map; import classycle.Analyser; import classycle.graph.AtomicVertex; /** * Checks a class graph for unwanted dependencies. The dependencies are * described by a dependency definition file (<tt>.ddf</tt>). * * @author Franz-Josef Elmer */ public class DependencyChecker { private final Analyser _analyser; private final ResultRenderer _renderer; private final DependencyProcessor _processor; /** * Creates a new instance. * Note, that the constructor does not create the graph. It only parses * <tt>dependencyDefinition</tt> as a preprocessing step. The calculation * of the graph is done in {@link #check(PrintWriter)}. * * @param analyser Analyzer instance. * @param dependencyDefinition Description (as read from a .ddf file) of the * dependencies to be checked. * @param renderer Output renderer for unwanted dependencies found. */ public DependencyChecker(Analyser analyser, String dependencyDefinition, Map properties, ResultRenderer renderer) { _analyser = analyser; _renderer = renderer; DependencyProperties dp = new DependencyProperties(properties); _processor = new DependencyProcessor(dependencyDefinition, dp, renderer); } /** * Checks the graph and write unwanted dependencies onto the specified * writer. * @return <tt>true</tt> if no unwanted dependency has been found. */ public boolean check(PrintWriter writer) { Result result = check(); writer.print(_renderer.render(result)); return result.isOk(); } /** * Checks the graph. */ public Result check() { AtomicVertex[] graph = _analyser.getClassGraph(); ResultContainer result = new ResultContainer(); while (_processor.hasMoreStatements()) { result.add(_processor.executeNextStatement(graph)); } return result; } /** * Runs the DependencyChecker application. * Exit 0 if no unwanted dependency found otherwise 1 is returned. */ public static void main(String[] args) { DependencyCheckerCommandLine commandLine = new DependencyCheckerCommandLine(args); if (!commandLine.isValid()) { System.out.println("Usage: java -cp classycle.jar " + "classycle.DependencyChecker " + commandLine.getUsage()); System.exit(1); } Analyser analyser = new Analyser(commandLine.getClassFiles(), commandLine.getPattern(), commandLine.getReflectionPattern(), commandLine.isMergeInnerClasses()); DependencyChecker dependencyChecker = new DependencyChecker(analyser, commandLine.getDependencyDefinition(), System.getProperties(), commandLine.getRenderer()); PrintWriter printWriter = new PrintWriter(System.out); boolean ok = dependencyChecker.check(printWriter); printWriter.flush(); System.exit(ok ? 0 : 1); } } ���������������������classycle-1.4/src/classycle/dependency/DependencyCheckerCommandLine.java����������������������������0000664�0000000�0000000�00000007114�12021221155�0026536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.io.File; import java.io.IOException; import classycle.CommandLine; import classycle.util.Text; /** * @author Franz-Josef Elmer */ public class DependencyCheckerCommandLine extends CommandLine { private static final String DEPENDENCIES = "-dependencies=", RENDERER = "-renderer="; private String _dependencyDefinition; private ResultRenderer _renderer; public DependencyCheckerCommandLine(String[] args) { super(args); } protected void handleOption(String argument) { if (argument.startsWith(DEPENDENCIES)) { handleDependenciesOption(argument.substring(DEPENDENCIES.length())); } else if (argument.startsWith(RENDERER)) { handleRenderer(argument.substring(RENDERER.length())); } else { super.handleOption(argument); } } /** Returns the usage of correct command line arguments and options. */ public String getUsage() { return DEPENDENCIES + "<description>|@<description file> " + "[" + RENDERER + "<fully qualified class name of a ResultRenderer>] " + super.getUsage(); } public String getDependencyDefinition() { return _dependencyDefinition; } public ResultRenderer getRenderer() { return _renderer == null ? new DefaultResultRenderer() : _renderer; } private void handleDependenciesOption(String option) { if (option.startsWith("@")) { try { option = Text.readTextFile(new File(option.substring(1))); } catch (IOException e) { System.err.println("Error in reading dependencies description file: " + e); option = ""; } } _dependencyDefinition = option; if (_dependencyDefinition.length() == 0) { _valid = false; } } private void handleRenderer(String className) { try { _renderer = (ResultRenderer) Class.forName(className).newInstance(); } catch (Exception e) { System.err.println("Error in creating ResultRenderer " + className + ": " + e); _valid = false; } } public boolean isValid() { return super.isValid() && _dependencyDefinition != null; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyDefinitionParser.java������������������������������0000664�0000000�0000000�00000040315�12021221155�0026330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.StringTokenizer; import classycle.util.AndStringPattern; import classycle.util.NotStringPattern; import classycle.util.OrStringPattern; import classycle.util.StringPattern; import classycle.util.WildCardPattern; /** * Parser for a dependency definition file. * * @author Franz-Josef Elmer */ public class DependencyDefinitionParser { public static final String INDEPENDENT_OF_KEY_WORD = "independentOf"; public static final String EXCLUDING_KEY_WORD = "excluding"; public static final String DIRECTLY_INDEPENDENT_OF_KEY_WORD = "directlyIndependentOf"; public static final String DEPENDENT_ONLY_ON_KEY_WORD = "dependentOnlyOn"; public static final String CHECK_KEY_WORD = "check"; public static final String LAYER_KEY_WORD = "layer"; public static final String SHOW_KEY_WORD = "show"; public static final String SETS_KEY_WORD = "sets"; public static final String CLASS_CYCLES_KEY_WORD = "absenceOfClassCycles"; public static final String PACKAGE_CYCLES_KEY_WORD = "absenceOfPackageCycles"; public static final String IN_KEY_WORD = "in"; public static final String LAYERING_OF_KEY_WORD = "layeringOf"; public static final String STRICT_LAYERING_OF_KEY_WORD = "strictLayeringOf"; private static final String[] INDEPENDENT = new String[] {INDEPENDENT_OF_KEY_WORD, DIRECTLY_INDEPENDENT_OF_KEY_WORD, DEPENDENT_ONLY_ON_KEY_WORD}; private static final String[] EXCLUDING = new String[] {EXCLUDING_KEY_WORD}; private static final String PROP_DEF_BEGIN = "{"; private static final String PROP_BEGIN = "${"; private static final String PROP_END = "}"; private final DependencyProperties _properties; private final ResultRenderer _renderer; final SetDefinitionRepository _setDefinitions = new SetDefinitionRepository(); final LayerDefinitionRepository _layerDefinitions = new LayerDefinitionRepository(); private final ArrayList _statements = new ArrayList(); public DependencyDefinitionParser(String dependencyDefinition, DependencyProperties properties, ResultRenderer renderer) { _properties = properties; _renderer = renderer; try { StringBuffer buffer = new StringBuffer(); BufferedReader reader = new BufferedReader(new StringReader( dependencyDefinition)); String line; int lineNumber = 0; int lineNumberOfCurrentLogicalLine = 1; while ((line = reader.readLine()) != null) { lineNumber++; line = line.trim(); if (!line.startsWith("#")) { buffer.append(line); if (line.endsWith("\\")) { buffer.deleteCharAt(buffer.length() - 1).append(' '); } else { String logicalLine = replaceProperties(new String(buffer).trim(), lineNumberOfCurrentLogicalLine); if (logicalLine.length() > 0) { parseLine(logicalLine, lineNumberOfCurrentLogicalLine); } buffer.setLength(0); lineNumberOfCurrentLogicalLine = lineNumber + 1; } } } } catch (IOException e) { throw new IllegalArgumentException(e.toString()); } } private String replaceProperties(String line, int lineNumber) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < line.length(); ) { int index = line.indexOf(PROP_BEGIN, i); if (index >= 0) { buffer.append(line.substring(i, index)); i = line.indexOf(PROP_END, index); if (i < 0) { throwException("Missing '" + PROP_END + "'.", lineNumber, -1); } String name = line.substring(index + PROP_BEGIN.length(), i); i += PROP_END.length(); String property = _properties.getProperty(name); if (property == null) { String message = "Undefines property " + line.substring(index, i); throwException(message, lineNumber, -1); } else { buffer.append(property); } } else { buffer.append(line.substring(i)); i = line.length(); } } return new String(buffer); } public Statement[] getStatements() { return (Statement[]) _statements.toArray(new Statement[0]); } private void parseLine(String line, int lineNumber) { if (line.startsWith(PROP_DEF_BEGIN)) { parsePropertyDefinition(line, lineNumber); return; } StringTokenizer tokenizer = new StringTokenizer(line); String[] tokens = new String[tokenizer.countTokens()]; for (int i = 0; i < tokens.length; i++) { tokens[i] = tokenizer.nextToken(); } String firstToken = tokens[0]; if (firstToken.startsWith("[")) { parseSetDefinition(tokens, lineNumber); } else if (firstToken.equals(SHOW_KEY_WORD)) { parseShowStatement(tokens, lineNumber); } else if (firstToken.equals(LAYER_KEY_WORD)) { parseLayerDefinition(tokens, lineNumber); } else if (firstToken.equals(CHECK_KEY_WORD)) { parseCheckStatement(tokens, lineNumber); } else { throwException("Expecting either a property definition, a set name, '" + SHOW_KEY_WORD + "', '" + LAYER_KEY_WORD + "', or '" + CHECK_KEY_WORD + "'.", lineNumber, 0); } } private void parsePropertyDefinition(String line, int lineNumber) { int index = line.indexOf(PROP_END); if (index < 0) { throwException("Missing '" + PROP_END + "' in property definition.", lineNumber, -1); } String name = line.substring(PROP_DEF_BEGIN.length(), index); String def = line.substring(index + PROP_END.length()).trim(); if (def.startsWith("=") == false) { throwException("Missing '=' in propety definition.", lineNumber, -1); } _properties.setProperty(name, def.substring(1).trim()); } private void parseSetDefinition(String[] tokens, int lineNumber) { String setName = tokens[0]; if (setName.endsWith("]") == false) { throwException("Set name has to end with ']'.", lineNumber, 0); } if (_setDefinitions.contains(setName)) { throwException("Set " + setName + " already defined.", lineNumber, 0); } checkForEqualCharacter(tokens, lineNumber, 1); StringPattern[][] lists = getLists(tokens, lineNumber, EXCLUDING, 2); if (lists[0].length == 0 && lists[1].length == 0) { throwException("Missing terms in set definition.", lineNumber, 2); } AndStringPattern definition = new AndStringPattern(); if (lists[0].length > 0) { definition.appendPattern(createOrSequence(lists[0])); } if (lists[1].length > 0) { definition.appendPattern(new NotStringPattern(createOrSequence(lists[1]))); } _setDefinitions.put(setName, definition); } private void checkForEqualCharacter(String[] tokens, int lineNumber, int index) { if (tokens.length < index + 1 || !tokens[index].equals("=")) { throwException("'=' missing.", lineNumber, index); } } private StringPattern createOrSequence(StringPattern[] patterns) { OrStringPattern result = new OrStringPattern(); for (int i = 0; i < patterns.length; i++) { result.appendPattern(patterns[i]); } return result; } private StringPattern createPattern(String term, int lineNumber, int tokenIndex) { StringPattern pattern = _setDefinitions.getPattern(term); if (pattern == null) { if (term.startsWith("[") && term.endsWith("]")) { throwException("Set " + term + " is undefined.", lineNumber, tokenIndex); } if (term.indexOf('.') < 0 && term.indexOf('*') < 0 && term.length() > 0 && Character.isLowerCase(term.charAt(0))) { throwException("Patterns without a '.' and a '*' should not start " + "with a lower-case letter: " + term, lineNumber, tokenIndex); } pattern = new WildCardPattern(term); } return pattern; } private void parseLayerDefinition(String[] tokens, int lineNumber) { if (tokens.length < 2) { throwException("Missing layer name.", lineNumber, 1); } String layerName = tokens[1]; if (_layerDefinitions.contains(layerName)) { throwException("Layer '" + layerName + "' already defined.", lineNumber, 1); } checkForEqualCharacter(tokens, lineNumber, 2); if (tokens.length < 4) { throwException("Missing terms in definition of layer '" + layerName + "'.", lineNumber, 3); } ArrayList layer = new ArrayList(); for (int i = 3; i < tokens.length; i++) { layer.add(createPattern(tokens[i], lineNumber, i)); } StringPattern[] sets = new StringPattern[layer.size()]; _layerDefinitions.put(layerName, (StringPattern[]) layer.toArray(sets)); } private void parseShowStatement(String[] tokens, int lineNumber) { if (tokens.length < 2) { throwException("Missing display preference(s).", lineNumber, 1); } Preference[] preferences = new Preference[tokens.length - 1]; for (int i = 0; i < preferences.length; i++) { preferences[i] = _renderer.getPreferenceFactory().get(tokens[i + 1]); if (preferences[i] == null) { throwException("Unknown display preference: " + tokens[i + 1], lineNumber, i + 1); } } _statements.add(new ShowStatement(_renderer, preferences)); } private void parseCheckStatement(String[] tokens, int lineNumber) { if (tokens.length < 2) { throwException("Missing checking statement.", lineNumber, 1); } if (tokens[1].equals(STRICT_LAYERING_OF_KEY_WORD) || tokens[1].equals(LAYERING_OF_KEY_WORD)) { createLayeringStatement(tokens, lineNumber); } else if (tokens[1].equals(SETS_KEY_WORD)) { createCheckSetStatements(tokens, lineNumber); } else if (tokens[1].equals(CLASS_CYCLES_KEY_WORD) || tokens[1].equals(PACKAGE_CYCLES_KEY_WORD)) { createCyclesStatement(tokens, lineNumber); } else { createDependencyStatement(tokens, lineNumber); } } private void createCyclesStatement(String[] tokens, int lineNumber) { boolean packageCycles = tokens[1].equals(PACKAGE_CYCLES_KEY_WORD); if (tokens.length != 6) { throwException("Invalid statement.", lineNumber, tokens.length); } if (tokens[2].equals(">") == false) { throwException("'>' expected.", lineNumber, 2); } int size = 0; try { size = Integer.parseInt(tokens[3]); } catch (NumberFormatException e) { throwException("Number expected.", lineNumber, 3); } if (size < 1) { throwException("Size has to be >= 1", lineNumber, 3); } if (tokens[4].equals(IN_KEY_WORD) == false) { throwException("'in' expected.", lineNumber, 4); } StringPattern pattern = createPattern(tokens[5], lineNumber, 4); _statements.add(new CheckCyclesStatement(pattern, size, packageCycles, _setDefinitions)); } private void createCheckSetStatements(String[] tokens, int lineNumber) { if (tokens.length < 3) { throwException("No sets to check.", lineNumber, 2); } for (int i = 2; i < tokens.length; i++) { StringPattern pattern = createPattern(tokens[i], lineNumber, i); _statements.add(new CheckSetStatement(pattern, _setDefinitions)); } } private void createLayeringStatement(String[] tokens, int lineNumber) { StringPattern[][] layers = new StringPattern[tokens.length - 2][]; for (int i = 0; i < layers.length; i++) { String name = tokens[i + 2]; layers[i] = _layerDefinitions.getLayer(name); if (layers[i] == null) { throwException("Undefined layer '" + name + "'.", lineNumber, i + 2); } } boolean strict = tokens[1].equals(STRICT_LAYERING_OF_KEY_WORD); _statements.add(new LayeringStatement(layers, strict, _setDefinitions, _layerDefinitions, _renderer)); } private void createDependencyStatement(String[] tokens, int lineNumber) { StringPattern[][] lists = getLists(tokens, lineNumber, INDEPENDENT, 1); if (lists[0].length == 0) { throwException("Missing start sets.", lineNumber, 1); } if (lists[1].length == 0) { throwException("Missing end sets. Probably one of the following " + "key words are missing: " + Arrays.asList(INDEPENDENT), lineNumber, tokens.length); } boolean directPathsOnly = DIRECTLY_INDEPENDENT_OF_KEY_WORD.equals( tokens[lists[0].length + 1]); _statements.add(new DependencyStatement(lists[0], lists[1], tokens[lists[0].length + 1], _setDefinitions, _renderer)); } private StringPattern[][] getLists(String[] tokens, int lineNumber, String[] keyWords, int startIndex) { ArrayList startSets = new ArrayList(); ArrayList endSets = new ArrayList(); ArrayList currentList = startSets; for (int i = startIndex; i < tokens.length; i++) { String token = tokens[i]; if (isAKeyWord(token, keyWords)) { if (currentList == endSets) { throwException("Invalid appearance of key word '" + token + "'.", lineNumber, i); } currentList = endSets; } else { currentList.add(createPattern(token, lineNumber, i)); } } StringPattern[][] result = new StringPattern[2][]; result[0] = (StringPattern[]) startSets.toArray(new StringPattern[0]); result[1] = (StringPattern[]) endSets.toArray(new StringPattern[0]); return result; } private boolean isAKeyWord(String token, String[] keyWords) { boolean result = false; for (int i = 0; i < keyWords.length; i++) { if (keyWords[i].equals(token)) { result = true; break; } } return result; } private void throwException(String message, int lineNumber, int tokenIndex) { StringBuffer buffer = new StringBuffer("Error in line "); buffer.append(lineNumber); if (tokenIndex >= 0) { buffer.append(" token ").append(tokenIndex + 1); } buffer.append(": ").append(message); throw new IllegalArgumentException(new String(buffer)); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyPathRenderer.java����������������������������������0000664�0000000�0000000�00000001375�12021221155�0025451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2011 Franz-Josef Elmer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package classycle.dependency; interface DependencyPathRenderer { void increaseIndentation(); void add(String nodeName); void decreaseIndentation(); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyPathsRenderer.java���������������������������������0000664�0000000�0000000�00000011201�12021221155�0025621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.HashSet; import java.util.Set; import classycle.graph.NameAttributes; import classycle.graph.Vertex; import classycle.graph.VertexCondition; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ public class DependencyPathsRenderer { private static final String INDENT = " "; private final Vertex[] _graph; private final VertexCondition _startSetCondition; private final VertexCondition _finalSetCondition; private final Set<Vertex> _vertices = new HashSet<Vertex>(); public DependencyPathsRenderer(Vertex[] graph, StringPattern startSetPattern, StringPattern finalSetPattern) { this(graph, new PatternVertexCondition(startSetPattern), new PatternVertexCondition(finalSetPattern)); } public DependencyPathsRenderer(Vertex[] graph, VertexCondition startSetCondition, VertexCondition finalSetCondition) { _graph = graph; _startSetCondition = startSetCondition; _finalSetCondition = finalSetCondition; for (int i = 0; i < graph.length; i++) { _vertices.add(graph[i]); } } public String renderGraph(final String lineStart) { final StringBuffer buffer = new StringBuffer(); DependencyPathRenderer renderer = new DependencyPathRenderer() { String _start = '\n' + lineStart; private int _indentation; public void increaseIndentation() { _indentation++; } public void add(String nodeName) { buffer.append(_start); for (int i = 0; i < _indentation; i++) { buffer.append(INDENT); } if (_indentation > 0) { buffer.append("-> "); } buffer.append(nodeName); } public void decreaseIndentation() { _indentation--; } }; renderGraph(renderer); return new String(buffer); } public void renderGraph(DependencyPathRenderer renderer) { Set<Vertex> visitedVertices = new HashSet<Vertex>(); for (int i = 0; i < _graph.length; i++) { Vertex vertex = _graph[i]; if (_startSetCondition.isFulfilled(vertex)) { renderer.add(getNameOf(vertex)); renderPaths(renderer, vertex, visitedVertices); } } } private void renderPaths(DependencyPathRenderer renderer, Vertex vertex, Set<Vertex> visitedVertices) { visitedVertices.add(vertex); renderer.increaseIndentation(); for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { Vertex headVertex = vertex.getHeadVertex(i); if (_vertices.contains(headVertex) && !_startSetCondition.isFulfilled(headVertex)) { renderer.add(getNameOf(headVertex)); if (!_finalSetCondition.isFulfilled(headVertex) && !visitedVertices.contains(headVertex)) { renderPaths(renderer, headVertex, visitedVertices); } } } renderer.decreaseIndentation(); } private String getNameOf(Vertex vertex) { return ((NameAttributes) vertex.getAttributes()).getName(); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyProcessor.java�������������������������������������0000664�0000000�0000000�00000006154�12021221155�0025045�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import classycle.graph.AtomicVertex; /** * Processor of {@link Statement Statements} as defined in a * dependency definition file. * * @author Franz-Josef Elmer */ public class DependencyProcessor { private final Statement[] _statements; private int _index; /** * Creates a new instance for the specified dependency definition. It also * parses the definition and creates all {@link Statement Statements}. * * @param dependencyDefinition Dependency definition as read from a * .ddf file. * @param properties Contains predefined properties and will also * be populated by definition in <code>dependencyDefinition</code>. * @param renderer Renderer for processing results. * @throws IllegalArgumentException if <tt>dependencyDefinition</tt> * is invalid. */ public DependencyProcessor(String dependencyDefinition, DependencyProperties properties, ResultRenderer renderer) { _statements = new DependencyDefinitionParser(dependencyDefinition, properties, renderer).getStatements(); } /** * Returns <tt>true</tt> if there are still unprocessed statements. * @return */ public boolean hasMoreStatements() { return _index < _statements.length; } /** * Executes the next unprocessed statement and returns its result. * @param graph The graph to be checked by the statement. * @return <tt>null</tt> if there is no unprocessed statement. */ public Result executeNextStatement(AtomicVertex[] graph) { return hasMoreStatements() ? _statements[_index++].execute(graph) : null; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyProperties.java������������������������������������0000664�0000000�0000000�00000004165�12021221155�0025222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Created on 07.04.2006 */ package classycle.dependency; import java.util.HashMap; import java.util.Map; final class DependencyProperties { private final Map _defaultProperties; private final Map _properties = new HashMap(); DependencyProperties() { this(new HashMap()); } DependencyProperties(Map defaultProperties) { _defaultProperties = defaultProperties; } String getProperty(String name) { String result = (String) _properties.get(name); if (result == null) { Object value = _defaultProperties.get(name); if (value instanceof String) { result = (String) value; } } return result; } void setProperty(String name, String value) { _properties.put(name, value); } }�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyResult.java����������������������������������������0000664�0000000�0000000�00000006373�12021221155�0024347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import classycle.graph.AtomicVertex; import classycle.util.StringPattern; /** * Result of a dependency check. * * @author Franz-Josef Elmer */ public class DependencyResult implements Result { static final String OK = "\tOK"; static final String DEPENDENCIES_FOUND = "\n Unexpected dependencies found:"; private final StringPattern _startSet; private final StringPattern _finalSet; private final String _statement; private final AtomicVertex[] _paths; private final boolean _ok; public DependencyResult(StringPattern startSet, StringPattern finalSet, String statement, AtomicVertex[] paths) { _startSet = startSet; _finalSet = finalSet; _statement = statement; _paths = paths; _ok = paths.length == 0; } /** * Returns <code>true</code> if and only if {@link #getPaths()} is empty. */ public boolean isOk() { return _ok; } /** * Returns the statement causing this result. */ public String getStatement() { return _statement; } /** * Returns the pattern describing the final set. */ public StringPattern getFinalSet() { return _finalSet; } /** * Returns the vertices of the paths of unwanted dependencies. * * @return an empty array if no unwanted dependencies have been found. */ public AtomicVertex[] getPaths() { return _paths; } /** * Returns the pattern describing the start set. */ public StringPattern getStartSet() { return _startSet; } public String toString() { StringBuffer buffer = new StringBuffer(_statement); if (_ok) { buffer.append(OK); } else { DependencyPathsRenderer renderer = new DependencyPathsRenderer(_paths, _startSet, _finalSet); buffer.append(DEPENDENCIES_FOUND).append(renderer.renderGraph(" ")); } return new String(buffer.append('\n')); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/DependencyStatement.java�������������������������������������0000664�0000000�0000000�00000014451�12021221155�0025031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import static classycle.dependency.DependencyDefinitionParser.DIRECTLY_INDEPENDENT_OF_KEY_WORD; import java.util.HashSet; import java.util.Set; import classycle.graph.AtomicVertex; import classycle.graph.PathsFinder; import classycle.graph.Vertex; import classycle.graph.VertexCondition; import classycle.util.OrStringPattern; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ public class DependencyStatement implements Statement { private static final class VertexUnionCondition implements VertexCondition { private final VertexCondition[] _conditions; VertexUnionCondition(VertexCondition[] conditions) { _conditions = conditions; } public boolean isFulfilled(Vertex vertex) { for (VertexCondition condition : _conditions) { if (condition.isFulfilled(vertex)) { return true; } } return false; } } private static final String CHECK = DependencyDefinitionParser.CHECK_KEY_WORD + ' '; private final StringPattern[] _startSets; private final StringPattern[] _finalSets; private final StringPattern _finalSet; private final String _dependencyType; private final VertexCondition[] _startConditions; private final VertexCondition[] _finalConditions; private final VertexCondition _finalCondition; private final SetDefinitionRepository _repository; private final ResultRenderer _renderer; public DependencyStatement(StringPattern[] startSets, StringPattern[] finalSets, String dependencyType, SetDefinitionRepository repository, ResultRenderer renderer) { _startSets = startSets; _finalSets = finalSets; _dependencyType = dependencyType; _repository = repository; _renderer = renderer; _startConditions = createVertexConditions(startSets); _finalConditions = createVertexConditions(finalSets); _finalSet = new OrStringPattern(_finalSets); _finalCondition = new VertexUnionCondition(_finalConditions); } private VertexCondition[] createVertexConditions(StringPattern[] patterns) { VertexCondition[] fromSets = new VertexCondition[patterns.length]; for (int i = 0; i < fromSets.length; i++) { fromSets[i] = new PatternVertexCondition(patterns[i]); } return fromSets; } public Result execute(AtomicVertex[] graph) { ResultContainer result = new ResultContainer(); boolean directPathsOnly = DIRECTLY_INDEPENDENT_OF_KEY_WORD.equals(_dependencyType); boolean dependsOnly = DependencyDefinitionParser.DEPENDENT_ONLY_ON_KEY_WORD.equals(_dependencyType); for (int i = 0; i < _startConditions.length; i++) { VertexCondition startCondition = _startConditions[i]; StringPattern startSet = _startSets[i]; if (dependsOnly) { Set<AtomicVertex> invalids = new HashSet<AtomicVertex>(); for (AtomicVertex vertex : graph) { if (startCondition.isFulfilled(vertex)) { for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) { Vertex headVertex = vertex.getHeadVertex(j); if (_finalCondition.isFulfilled(headVertex) == false && startCondition.isFulfilled(headVertex) == false) { invalids.add(vertex); invalids.add((AtomicVertex) headVertex); } } } } result.add(new DependencyResult(startSet, _finalSet, toString(startSet, _finalSet), invalids.toArray(new AtomicVertex[0]))); } else { for (int j = 0; j < _finalConditions.length; j++) { PathsFinder finder = new PathsFinder(startCondition, _finalConditions[j], _renderer .onlyShortestPaths(), directPathsOnly); result.add(new DependencyResult(startSet, _finalSets[j], toString(i, j), finder .findPaths(graph))); } } } return result; } private String toString(int i, int j) { return toString(_startSets[i], _finalSets[j]); } private String toString(StringPattern startSet, StringPattern finalSet) { StringBuffer buffer = new StringBuffer(CHECK); buffer.append(_repository.toString(startSet)).append(' ') .append(_dependencyType).append(' ') .append(_repository.toString(finalSet)); return new String(buffer); } public String toString() { StringBuffer buffer = new StringBuffer(CHECK); for (int i = 0; i < _startSets.length; i++) { buffer.append(_repository.toString(_startSets[i])).append(' '); } buffer.append(_dependencyType).append(' '); for (int i = 0; i < _finalSets.length; i++) { buffer.append(_repository.toString(_finalSets[i])).append(' '); } return new String(buffer.substring(0, buffer.length() - 1)); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/LayerDefinitionRepository.java�������������������������������0000664�0000000�0000000�00000004252�12021221155�0026251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.HashMap; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ class LayerDefinitionRepository { private final HashMap _nameToLayerMap = new HashMap(); private final HashMap _layerToNameMap = new HashMap(); public int getNumberOfDefinitions() { return _nameToLayerMap.size(); } public void put(String name, StringPattern[] layer) { _nameToLayerMap.put(name, layer); _layerToNameMap.put(layer, name); } public StringPattern[] getLayer(String name) { return (StringPattern[]) _nameToLayerMap.get(name); } public boolean contains(String name) { return _nameToLayerMap.containsKey(name); } public String getName(StringPattern[] layer) { return (String) _layerToNameMap.get(layer); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/LayeringStatement.java���������������������������������������0000664�0000000�0000000�00000010312�12021221155�0024515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import static classycle.dependency.DependencyDefinitionParser.DIRECTLY_INDEPENDENT_OF_KEY_WORD; import classycle.graph.AtomicVertex; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ public class LayeringStatement implements Statement { private final StringPattern[][] _layers; private final boolean _strictLayering; private final SetDefinitionRepository _repository; private final LayerDefinitionRepository _layerRepository; private final ResultRenderer _renderer; public LayeringStatement(StringPattern[][] layers, boolean strictLayering, SetDefinitionRepository repository, LayerDefinitionRepository layerRepository, ResultRenderer renderer) { _layers = layers; _repository = repository; _layerRepository = layerRepository; _strictLayering = strictLayering; _renderer = renderer; } public Result execute(AtomicVertex[] graph) { ResultContainer result = new ResultContainer(); for (int i = 0; i < _layers.length; i++) { checkIntraLayerDependencies(result, _layers[i], graph); for (int j = i + 1; j < _layers.length; j++) { DependencyStatement s = new DependencyStatement(_layers[i], _layers[j], DIRECTLY_INDEPENDENT_OF_KEY_WORD, _repository, _renderer); result.add(s.execute(graph)); } if (_strictLayering) { for (int j = i - 2; j >= 0; j--) { DependencyStatement s = new DependencyStatement(_layers[i], _layers[j], DIRECTLY_INDEPENDENT_OF_KEY_WORD, _repository, _renderer); result.add(s.execute(graph)); } } } return result; } private void checkIntraLayerDependencies(ResultContainer result, StringPattern[] patterns, AtomicVertex[] graph) { StringPattern[] startSets = new StringPattern[1]; StringPattern[] endSets = new StringPattern[patterns.length - 1]; for (int i = 0; i < patterns.length; i++) { startSets[0] = patterns[i]; System.arraycopy(patterns, 0, endSets, 0, i); System.arraycopy(patterns, i + 1, endSets, i, patterns.length - i - 1); DependencyStatement s = new DependencyStatement(startSets, endSets, DIRECTLY_INDEPENDENT_OF_KEY_WORD, _repository, _renderer); result.add(s.execute(graph)); } } public String toString() { StringBuffer buffer = new StringBuffer("check "); buffer.append(_strictLayering ? "strictLayeringOf" : "layeringOf"); for (int i = 0; i < _layers.length; i++) { buffer.append(' ').append(_layerRepository.getName(_layers[i])); } return new String(buffer); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/PatternVertexCondition.java����������������������������������0000664�0000000�0000000�00000004276�12021221155�0025554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import classycle.graph.Attributes; import classycle.graph.NameAttributes; import classycle.graph.Vertex; import classycle.graph.VertexCondition; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ public class PatternVertexCondition implements VertexCondition { private final StringPattern _pattern; public PatternVertexCondition(StringPattern pattern) { _pattern = pattern; } public boolean isFulfilled(Vertex vertex) { boolean result = false; if (vertex != null) { Attributes attributes = vertex.getAttributes(); if (attributes instanceof NameAttributes) { result = _pattern.matches(((NameAttributes) attributes).getName()); } } return result; } public String toString() { return _pattern.toString(); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/Preference.java����������������������������������������������0000664�0000000�0000000�00000002754�12021221155�0023147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * @author Franz-Josef Elmer */ public interface Preference { public String getKey(); } ��������������������classycle-1.4/src/classycle/dependency/PreferenceFactory.java���������������������������������������0000664�0000000�0000000�00000002776�12021221155�0024503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * @author Franz-Josef Elmer */ public interface PreferenceFactory { public Preference get(String key); } ��classycle-1.4/src/classycle/dependency/Result.java��������������������������������������������������0000664�0000000�0000000�00000003162�12021221155�0022341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * Common interface of all result checking statements. * * @author Franz-Josef Elmer */ public interface Result { /** * Returns <code>true</code> if the checking result is positive. */ public boolean isOk(); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/ResultContainer.java�����������������������������������������0000664�0000000�0000000�00000004757�12021221155�0024217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.ArrayList; import java.util.List; /** * Container of {@link Result} instances. * * @author Franz-Josef Elmer */ public class ResultContainer implements Result { private final List<Result> _list = new ArrayList<Result>(); /** * Adds a result. */ public void add(Result result) { _list.add(result); } /** * Returns the number of added results. */ public int getNumberOfResults() { return _list.size(); } /** * Returns the result with specified index. */ public Result getResult(int index) { return _list.get(index); } /** * Returns <code>true</code> if all added {@link Result} instances returned <code>true</code>. */ public boolean isOk() { for (int i = 0, n = _list.size(); i < n; i++) { if (getResult(i).isOk() == false) { return false; } } return true; } public String toString() { StringBuffer buffer = new StringBuffer(); for (int i = 0, n = getNumberOfResults(); i < n; i++) { buffer.append(getResult(i)); } return new String(buffer); } } �����������������classycle-1.4/src/classycle/dependency/ResultRenderer.java������������������������������������������0000664�0000000�0000000�00000003563�12021221155�0024035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * Renderer for dependency checks. * * @author Franz-Josef Elmer */ public abstract class ResultRenderer { protected boolean _shortestPaths = true; public boolean onlyShortestPaths() { return _shortestPaths; } public abstract PreferenceFactory getPreferenceFactory(); public abstract void considerPreference(Preference preference); public abstract Result getDescriptionOfCurrentPreferences(); public abstract String render(Result result); } ���������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/SetDefinitionRepository.java���������������������������������0000664�0000000�0000000�00000004516�12021221155�0025733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.HashMap; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ class SetDefinitionRepository { private final HashMap _nameToPatternMap = new HashMap(); private final HashMap _patternToNameMap = new HashMap(); public int getNumberOfDefinitions() { return _nameToPatternMap.size(); } public void put(String name, StringPattern pattern) { _nameToPatternMap.put(name, pattern); _patternToNameMap.put(pattern, name); } public StringPattern getPattern(String name) { return (StringPattern) _nameToPatternMap.get(name); } public boolean contains(String name) { return _nameToPatternMap.containsKey(name); } public String getName(StringPattern pattern) { return (String) _patternToNameMap.get(pattern); } public String toString(StringPattern pattern) { String name = getName(pattern); return name == null ? pattern.toString() : name; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/ShowStatement.java�������������������������������������������0000664�0000000�0000000�00000004106�12021221155�0023667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.Arrays; import classycle.graph.AtomicVertex; /** * @author Franz-Josef Elmer */ public class ShowStatement implements Statement { private final ResultRenderer _renderer; private final Preference[] _preferences; public ShowStatement(ResultRenderer renderer, Preference[] preferences) { _renderer = renderer; _preferences = preferences; } public Result execute(AtomicVertex[] graph) { for (int i = 0; i < _preferences.length; i++) { _renderer.considerPreference(_preferences[i]); } return _renderer.getDescriptionOfCurrentPreferences(); } public String toString() { return Arrays.asList(_preferences).toString(); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/Statement.java�����������������������������������������������0000664�0000000�0000000�00000003046�12021221155�0023030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import classycle.graph.AtomicVertex; /** * @author Franz-Josef Elmer */ public interface Statement { public Result execute(AtomicVertex[] graph); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/TextResult.java����������������������������������������������0000664�0000000�0000000�00000004011�12021221155�0023200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; /** * Result as a text. * * @author Franz-Josef Elmer */ public class TextResult implements Result { private final String _text; private final boolean _ok; /** * Creates an instance with specified text which is ok. */ public TextResult(String text) { this(text, true); } /** * Creates an instance with specified text and specified OK flag. */ public TextResult(String text, boolean ok) { _text = text; _ok = ok; } public boolean isOk() { return _ok; } /** * Returns the text specified in the constructor. */ public String toString() { return _text; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/dependency/XMLResultRenderer.java���������������������������������������0000664�0000000�0000000�00000016542�12021221155�0024417�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2011, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.dependency; import java.util.List; import java.util.Stack; import classycle.graph.AtomicVertex; import classycle.graph.Attributes; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; import classycle.renderer.AbstractStrongComponentRenderer; import classycle.util.StringPattern; import classycle.util.Text; /** * Renderer which renders dependency checking results as XML. It ignores preferences. * * @author Franz-Josef Elmer */ public class XMLResultRenderer extends ResultRenderer { private static final String ELEMENT_DEPENDENCY_RESULT = "dependency-checking-results"; private static final String ATTRIBUTE_STATEMENT = "statement"; private static final class XMLBuilder { private static final int INDENTATION_INCREMENT = 2; private final StringBuilder _builder = new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>\n"); private Stack<String> _stack = new Stack<String>(); private boolean _unfinishedStartTag; private boolean _textAdded; void begin(String element) { if (_unfinishedStartTag) { _builder.append(">\n"); } indent(); _builder.append("<").append(element); _stack.push(element); _unfinishedStartTag = true; } void attribute(String name, String value) { _builder.append(' ').append(name).append("=\'").append(Text.excapeForXML(value)).append("\'"); } void text(String text) { _builder.append(">").append(Text.excapeForXML(text)); _unfinishedStartTag = false; _textAdded = true; } void end() { String element = _stack.pop(); if (_unfinishedStartTag) { _builder.append("/>\n"); _unfinishedStartTag = false; } else { if (_textAdded == false) { indent(); } _textAdded = false; _builder.append("</").append(element).append(">\n"); } } private void indent() { for (int i = 0; i < _stack.size() * INDENTATION_INCREMENT; i++) { _builder.append(' '); } } @Override public String toString() { return _builder.toString(); } } @Override public PreferenceFactory getPreferenceFactory() { return new PreferenceFactory() { public Preference get(final String key) { return new Preference() { public String getKey() { return key; } }; } }; } @Override public void considerPreference(Preference preference) { } @Override public Result getDescriptionOfCurrentPreferences() { return new TextResult(""); } @Override public String render(Result result) { XMLBuilder builder = new XMLBuilder(); builder.begin(ELEMENT_DEPENDENCY_RESULT); addTo(builder, result); builder.end(); return builder.toString(); } private void addTo(XMLBuilder builder, Result result) { if (result instanceof CyclesResult) { addTo(builder, (CyclesResult) result); } else if (result instanceof DependencyResult) { addTo(builder, (DependencyResult) result); } else if (result instanceof ResultContainer) { addTo(builder, (ResultContainer) result); } else if (result instanceof TextResult) { addTo(builder, (TextResult) result); } } private void addTo(XMLBuilder builder, CyclesResult result) { builder.begin("cycles"); builder.attribute(ATTRIBUTE_STATEMENT, result.getStatement()); builder.attribute("vertex-type", result.isPackageCycle() ? "package" : "class"); List<StrongComponent> cycles = result.getCycles(); for (StrongComponent component : cycles) { builder.begin("cycle"); builder.attribute("name", AbstractStrongComponentRenderer.createName(component)); for (int i = 0, n = component.getNumberOfVertices(); i < n; i++) { builder.begin("class"); Attributes attributes = component.getVertex(i).getAttributes(); if (attributes instanceof NameAttributes) { builder.text(((NameAttributes) attributes).getName()); } builder.end(); } builder.end(); } builder.end(); } private void addTo(XMLBuilder builder, DependencyResult result) { builder.begin("unexpected-dependencies"); builder.attribute(ATTRIBUTE_STATEMENT, result.getStatement()); AtomicVertex[] paths = result.getPaths(); StringPattern startSet = result.getStartSet(); StringPattern finalSet = result.getFinalSet(); DependencyPathsRenderer renderer = new DependencyPathsRenderer(paths, startSet, finalSet); renderer.renderGraph(createPathRenderer(builder)); builder.end(); } private DependencyPathRenderer createPathRenderer(final XMLBuilder builder) { return new DependencyPathRenderer() { private int _level; private boolean _openTag; public void increaseIndentation() { _openTag = false; _level++; } public void decreaseIndentation() { _level--; if (_openTag) { builder.end(); } _openTag = false; builder.end(); } public void add(String nodeName) { if (_openTag) { builder.end(); } builder.begin("node"); builder.attribute("name", nodeName); _openTag = true; } }; } private void addTo(XMLBuilder builder, ResultContainer result) { int numberOfResults = result.getNumberOfResults(); for (int i = 0; i < numberOfResults; i++) { addTo(builder, result.getResult(i)); } } private void addTo(XMLBuilder builder, TextResult result) { if (result.isOk() == false || result.toString().trim().length() > 0) { builder.begin(result.isOk() ? "info" : "checking-error"); builder.text(result.toString()); builder.end(); } } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0017201�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/AtomicVertex.java�������������������������������������������������0000664�0000000�0000000�00000006230�12021221155�0022457�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * A subclass of {@link Vertex} with the following additional properties: * <ul><li>A flag indicating whether this vertex belongs to the graph or not. * <li>The order of visiting. * <li>The low function. * </ul> * The last two properties are used in Tarjan's algorithm to find the * strong components (see {@link StrongComponentProcessor}). * * @author Franz-Josef Elmer */ public class AtomicVertex extends Vertex { private boolean _graphVertexDefaultValue = true; private boolean _graphVertex; private int _order; private int _low; /** Creates an instance for the specified attributes. */ public AtomicVertex(Attributes attributes) { super(attributes); } /** * Reset this instance. That is, it becomes a unvisited vertex * where <tt>order = low = -1</tt>. Whether it is a graph vertex or not * depends on the default value defined by the method * {@link #setDefaultValueOfGraphVertexFlag}. */ public void reset() { super.reset(); _graphVertex = _graphVertexDefaultValue; _order = -1; _low = -1; } /** Returns <tt>true</tt> if this vertex belongs to a graph. */ public boolean isGraphVertex() { return _graphVertex; } /** * Sets the default value of graphVertex flag. * @see #reset() */ public void setDefaultValueOfGraphVertexFlag(boolean flag) { _graphVertexDefaultValue = flag; } /** Returns the order of visiting. */ public int getOrder() { return _order; } /** Sets the order of visiting. */ public void setOrder(int order) { _order = order; } /** Returns the current value of the low function. */ public int getLow() { return _low; } /** Sets the current value of the low function. */ public void setLow(int low) { _low = low; } } //class������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/Attributes.java���������������������������������������������������0000664�0000000�0000000�00000003224�12021221155�0022173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * Interface of any general set of attributes a {@link Vertex} may * have. These attributes are neither used or modified by any parsing or * searching process. * * @author Franz-Josef Elmer */ public interface Attributes extends Comparable { } //interface����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/GraphAttributes.java����������������������������������������������0000664�0000000�0000000�00000007031�12021221155�0023155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * Attributes of a graph. The following properties * can be accessed with this interface: * <dl><dt>Girth:</dt><dd>The length of the shortest cycle.</dd> * <dt>Eccentricities:</dt> * <dd>The eccentricity for each vertex of the graph. The eccentricity of * a vertex is the largest <em>distance</em> to other vertices of the * graph. The distance between vertex A and B is defined as the * shortest path from A to B. The distance is infinite if there is * no path from A to B. * <dt>Diameter:</dt><dd>The largest eccentricity.</dd> * <dt>Radius:</dt><dd>The smallest eccentricity.</dd> * <dt>Center:</dt> * <dd>The set of vertices of the graph with the smallest eccentricities. * </dd> * <dt>Maximum fragment sizes:</dt> * <dd>The maximum fragment sizes for each vertex of the graph. The * maximum fragment size of a vertex is defined as the size of the * largest strong component of the graph after the vertex has been * removed. * </dd> * <dt>Best fragment size:</dt> * <dd>The smallest maximum fragment size.</dd> * <dt>Best fragmenters:</dt> * <dd>The set of vertices of the graph with smallest maximum fragment size. * </dd> * </dl> * * @author Franz-Josef Elmer */ public interface GraphAttributes extends Attributes { /** Returns the girth. */ public int getGirth(); /** Returns the radius. */ public int getRadius(); /** Returns the diameter. */ public int getDiameter(); /** Returns the vertices of the center. */ public Vertex[] getCenterVertices(); /** * Returns the eccentricies of all vertices of a {@link StrongComponent}. */ public int[] getEccentricities(); /** * Returns the maximum fragment sizes of all vertices of * a {@link StrongComponent}. */ public int[] getMaximumFragmentSizes(); /** Returns the best fragment size. */ public int getBestFragmentSize(); /** * Returns those vertices of a {@link StrongComponent} where the maximum * fragment size is equal to the best fragment size. */ public Vertex[] getBestFragmenters(); } //interface�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/GraphProcessor.java�����������������������������������������������0000664�0000000�0000000�00000010501�12021221155�0023002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * Abstract class for all algorithms based on deep search first. * This class is designed in accordance with the Template Method pattern. * The basic algorithm (implemented in the method * {@link #process}) reads: * <pre> * vertex.visit(); * processBefore(vertex); * for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { * processArc(vertex, vertex.getHeadVertex(i)); * } * processAfter(vertex); * </pre> * The methods {@link #initializeProcessing initializeProcessing()}, * {@link #processBefore processBefore()}, * {@link #processArc processArc()}, and * {@link #processAfter processAfter()} have to be implemented * by concrete classes. * <p> * The class will be used by creating an instance and invoking * {@link #deepSearchFirst deepSearchFirst()} one or several times. * Either the graph will be * modified or some result objects are created which can be obtained * by special methods defined in concrete subclasses. Note, that * a <tt>GraphProcessor</tt> is not thread-safe. * * @author Franz-Josef Elmer */ public abstract class GraphProcessor { /** * Performs a deep search first of the specified graph. * First, processing will be initialized and all vertices of the graph * will be reset. Then for all unvisited vertices the * method <tt>process(Vertex)</tt> will be invoked. At last, * processing will be finished. * @param graph A directed graph. */ public void deepSearchFirst(Vertex[] graph) { initializeProcessing(graph); for (int i = 0; i < graph.length; i++) { graph[i].reset(); } for (int i = 0; i < graph.length; i++) { if (!graph[i].isVisited()) { process(graph[i]); } } finishProcessing(graph); } /** Processes the specified vertex. */ protected void process(Vertex vertex) { vertex.visit(); processBefore(vertex); for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { processArc(vertex, vertex.getHeadVertex(i)); } processAfter(vertex); } /** * Initializes processing. Will be called in method * {@link #deepSearchFirst}. */ protected abstract void initializeProcessing(Vertex[] graph); /** * Processes the specified vertex before its outgoing arcs are processed. * @param vertex Vertex to be processed. */ protected abstract void processBefore(Vertex vertex); /** * Processes the arc specified by tail and head vertices. * @param tail Tail vertex of the arc. * @param head Head vertex of the arc. */ protected abstract void processArc(Vertex tail, Vertex head); /** * Processes the specified vertex after its arcs have been processed. * @param vertex Vertex to be processed. */ protected abstract void processAfter(Vertex vertex); /** * Finishes processing. Will be called in method * {@link #deepSearchFirst}. */ protected abstract void finishProcessing(Vertex[] graph); }�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/LongestWalkProcessor.java�����������������������������������������0000664�0000000�0000000�00000010114�12021221155�0024173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.Arrays; import java.util.Comparator; /** * Calculates for each vertex the longest walk. This processor assumes * that the graph has no cycles. * * @author Franz-Josef Elmer */ public class LongestWalkProcessor extends GraphProcessor { /** Does nothing. */ protected void initializeProcessing(Vertex[] graph) {} /** * Resets the specified vertex. * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link StrongComponent}. */ protected void processBefore(Vertex vertex) { StrongComponent component = castAsStrongComponent(vertex); component.setActive(true); component.setLongestWalk(0); } /** * Processes arc from <tt>tail</tt> to <tt>head</tt>. * Calculates the longest walk of <tt>tail</tt>. * @throws IllegalArgumentException if both vertices are not instances * of {@link StrongComponent} or if <tt>head</tt> is visited and * active which indicates a cycle in the graph. */ protected void processArc(Vertex tail, Vertex head) { StrongComponent t = castAsStrongComponent(tail); StrongComponent h = castAsStrongComponent(head); if (!h.isVisited()) { process(h); } else if (h.isActive()) { // Oops! should never be happen if the graph has been created // with StrongComponentProcessor throw new IllegalArgumentException(h + " is not a strong component."); } t.setLongestWalk(Math.max(t.getLongestWalk(), 1 + h.getLongestWalk())); } /** * Deactivate the specified vertex. * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link StrongComponent}. */ protected void processAfter(Vertex vertex) { castAsStrongComponent(vertex).setActive(false); } /** * Finishes processing by sorting the result in accordance with the * walk length. */ protected void finishProcessing(Vertex[] graph) { Arrays.sort(graph, new Comparator() { public int compare(Object obj1, Object obj2) { return ((StrongComponent) obj1).getLongestWalk() - ((StrongComponent) obj2).getLongestWalk(); } }); } /** * Casts the specified vertex as a {@link StrongComponent}. * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link StrongComponent}. */ private StrongComponent castAsStrongComponent(Vertex vertex) { if (vertex instanceof StrongComponent) { return (StrongComponent) vertex; } else { throw new IllegalArgumentException( vertex + " is not an instance of StrongComponent"); } } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/NameAttributes.java�����������������������������������������������0000664�0000000�0000000�00000003644�12021221155�0023002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * @author Franz-Josef Elmer */ public abstract class NameAttributes implements Attributes { private final String _name; public NameAttributes(String name) { _name = name; } /** Returns the name. */ public String getName() { return _name; } public int compareTo(Object object) { int result = -1; if (object instanceof NameAttributes && _name != null) { result = _name.compareTo(((NameAttributes) object).getName()); } return result; } public abstract int getSize(); } ��������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/PathsFinder.java��������������������������������������������������0000664�0000000�0000000�00000020625�12021221155�0022260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.HashSet; /** * Class searching for all (or only the shortest) paths between classes * of a start set and classes of a final set. * * @author Franz-Josef Elmer */ public class PathsFinder { private final VertexCondition _startSetCondition; private final VertexCondition _finalSetCondition; private final boolean _shortestPathsOnly; private final boolean _directPathsOnly; /** * Creates an instance for the specified vertex conditions. * @param startSetCondition Condition defining the start set. * @param finalSetCondition Condition defining the final set. * @param shortestPathsOnly if <code>true</code> only the shortest * paths are returned. */ public PathsFinder(VertexCondition startSetCondition, VertexCondition finalSetCondition, boolean shortestPathsOnly) { this(startSetCondition, finalSetCondition, shortestPathsOnly, false); } /** * Creates an instance for the specified vertex conditions. * @param startSetCondition Condition defining the start set. * @param finalSetCondition Condition defining the final set. * @param shortestPathsOnly if <code>true</code> only the shortest * paths are returned. * @param directPathsOnly if <code>true</code> only paths of length 1 * are returned. */ public PathsFinder(VertexCondition startSetCondition, VertexCondition finalSetCondition, boolean shortestPathsOnly, boolean directPathsOnly) { _startSetCondition = startSetCondition; _finalSetCondition = finalSetCondition; _shortestPathsOnly = shortestPathsOnly; _directPathsOnly = directPathsOnly; } public VertexCondition getFinalSetCondition() { return _finalSetCondition; } public boolean isShortestPathsOnly() { return _shortestPathsOnly; } public VertexCondition getStartSetCondition() { return _startSetCondition; } /** * Finds all paths from the specified start vertices to the vertices * fullfilling the specified condition. * @param graph Complete graph. * @return All vertices including start and end vertices defining the * subgraph with all paths. */ public AtomicVertex[] findPaths(AtomicVertex[] graph) { prepareGraph(graph); HashSet pathVertices = new HashSet(); HashSet currentPath = new HashSet(); for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = graph[i]; if (_startSetCondition.isFulfilled(vertex)) { if (_directPathsOnly) { findDirectPaths(vertex, pathVertices); } else { prepareIfFinal(vertex); int pathLength = calculateShortestPath(vertex, currentPath); if (pathLength < Integer.MAX_VALUE) { vertex.setOrder(pathLength); followPaths(vertex, pathVertices); } } } } return (AtomicVertex[]) pathVertices.toArray( new AtomicVertex[pathVertices.size()]); } private void findDirectPaths(AtomicVertex vertex, HashSet pathVertices) { if (_finalSetCondition.isFulfilled(vertex)) { pathVertices.add(vertex); } else { for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { Vertex headVertex = vertex.getHeadVertex(i); if (_finalSetCondition.isFulfilled(headVertex)) { pathVertices.add(vertex); pathVertices.add(headVertex); } } } } private void prepareGraph(AtomicVertex[] graph) { for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = graph[i]; prepareVertex(vertex); for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) { prepareVertex((AtomicVertex) vertex.getHeadVertex(j)); } } } private void prepareVertex(AtomicVertex vertex) { vertex.reset(); vertex.setOrder(Integer.MAX_VALUE); if (_startSetCondition.isFulfilled(vertex)) { vertex.visit(); } } private int calculateShortestPath(AtomicVertex vertex, HashSet currentPath) { currentPath.add(vertex); int shortestPath = Integer.MAX_VALUE; for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { AtomicVertex nextVertex = (AtomicVertex) vertex.getHeadVertex(i); prepareIfFinal(nextVertex); int pathLength = _startSetCondition.isFulfilled(nextVertex) ? Integer.MAX_VALUE : nextVertex.getOrder(); if (!currentPath.contains(nextVertex) && !nextVertex.isVisited()) { pathLength = calculateShortestPath(nextVertex, currentPath); nextVertex.setOrder(pathLength); nextVertex.visit(); } shortestPath = Math.min(shortestPath, pathLength); } currentPath.remove(vertex); if (shortestPath < Integer.MAX_VALUE) { shortestPath++; } return shortestPath; } private void prepareIfFinal(AtomicVertex vertex) { if (_finalSetCondition.isFulfilled(vertex)) { vertex.visit(); vertex.setOrder(0); } } private void followPaths(AtomicVertex vertex, HashSet pathVertices) { pathVertices.add(vertex); int shortestPathLength = vertex.getOrder() - 1; for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { AtomicVertex nextVertex = (AtomicVertex) vertex.getHeadVertex(i); int pathLength = nextVertex.getOrder(); if (pathLength < Integer.MAX_VALUE && !pathVertices.contains(nextVertex)) { if (!_shortestPathsOnly || pathLength == shortestPathLength) { pathVertices.add(nextVertex); if (pathLength > 0) { followPaths(nextVertex, pathVertices); } } } } } // private int search(AtomicVertex vertex, HashSet currentPath, // HashSet pathVertices) // { // currentPath.add(vertex); // boolean found = false; // int shortestPath = Integer.MAX_VALUE; // for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) // { // AtomicVertex nextVertex = (AtomicVertex) vertex.getHeadVertex(i); // int pathLength = nextVertex.getOrder(); // if (!nextVertex.isVisited() && !currentPath.contains(nextVertex)) // { // pathLength = search(nextVertex, currentPath, pathVertices); // nextVertex.setOrder(pathLength); // nextVertex.visit(); // } // shortestPath = Math.min(shortestPath, pathLength); // } // for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) // { // AtomicVertex nextVertex = (AtomicVertex) vertex.getHeadVertex(i); // int pathLength = nextVertex.getOrder(); // if (pathLength < Integer.MAX_VALUE) // { // if (!_shortestPathsOnly || pathLength == shortestPath) // { // pathVertices.add(nextVertex); // } // } // } // currentPath.remove(vertex); // if (shortestPath < Integer.MAX_VALUE) // { // shortestPath++; // } // return shortestPath; // } } �����������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/StrongComponent.java����������������������������������������������0000664�0000000�0000000�00000023515�12021221155�0023211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.ArrayList; import java.util.HashMap; import java.util.Vector; /** * A strong component is a subgraph of a directed graph where every two * vertices are mutually reachable. * * @author Franz-Josef Elmer */ public class StrongComponent extends Vertex { private static class GeometryAttributes implements GraphAttributes { private int _girth; private int _radius; private int _diameter; private ArrayList _centerVertices = new ArrayList(); private int[] _eccentricities; private int[] _maximumFragmentSizes; private int _bestFragmentSize; private ArrayList _bestFragmenters = new ArrayList(); public GeometryAttributes() {} public int getGirth() { return _girth; } void setGirth(int girth) { _girth = girth; } public int getRadius() { return _radius; } public int getDiameter() { return _diameter; } public int getBestFragmentSize() { return _bestFragmentSize; } public Vertex[] getCenterVertices() { return (Vertex[]) _centerVertices.toArray( new Vertex[_centerVertices.size()]); } void addVertex(Vertex vertex) { _centerVertices.add(vertex); } public Vertex[] getBestFragmenters() { return (Vertex[]) _bestFragmenters.toArray( new Vertex[_bestFragmenters.size()]); } void addFragmenter(Vertex vertex) { _bestFragmenters.add(vertex); } public int[] getEccentricities() { return _eccentricities; } void setEccentricities(int[] eccentricities) { _eccentricities = eccentricities; // Calculate radius and diameter _radius = Integer.MAX_VALUE; _diameter = 0; for (int i = 0; i < eccentricities.length; i++) { _radius = Math.min(_radius, eccentricities[i]); _diameter = Math.max(_diameter, eccentricities[i]); } } public int[] getMaximumFragmentSizes() { return _maximumFragmentSizes; } void setMaximumFragmentSizes(int[] maximumFragmentSizes) { _maximumFragmentSizes = maximumFragmentSizes; _bestFragmentSize = Integer.MAX_VALUE; for (int i = 0; i < maximumFragmentSizes.length; i++) { _bestFragmentSize = Math.min(_bestFragmentSize, maximumFragmentSizes[i]); } } public int compareTo(Object object) { int result = 1; if (object instanceof GeometryAttributes && _bestFragmenters.size() > 0) { ArrayList list = ((GeometryAttributes) object)._bestFragmenters; if (list.size() > 0) { Attributes attributes = ((Vertex) _bestFragmenters.get(0)).getAttributes(); Attributes objectAttributes = ((Vertex) list.get(0)).getAttributes(); result = attributes.compareTo(objectAttributes); } } return result; } } private final Vector _vertices = new Vector(); private boolean _active; private int _longestWalk; /** * Default constructor. The {@link Attributes} of a strong component will * a <tt>null</tt> pointer. */ public StrongComponent() { super(new GeometryAttributes()); } /** Returns the number of vertices building this strong component. */ public int getNumberOfVertices() { return _vertices.size(); } /** Returns the vertex of the specified index. */ public AtomicVertex getVertex(int index) { return (AtomicVertex) _vertices.elementAt(index); } /** * Adds the specified vertex to this strong component. Note, that added * vertices are inserted at index 0 of the list of vertices. */ public void addVertex(AtomicVertex vertex) { _vertices.insertElementAt(vertex, 0); } /** * Calculates all graph properties of this component. * These properties can be obtained from <tt>getAttributes</tt> casted as * {@link GraphAttributes}. */ public void calculateAttributes() { HashMap indexMap = calculateIndexMap(); int[][] distances = calculateDistances(indexMap); // Calculate girth and eccentricity GeometryAttributes attributes = (GeometryAttributes) getAttributes(); int girth = Integer.MAX_VALUE; int[] eccentricities = new int[distances.length]; for (int i = 0; i < distances.length; i++) { girth = Math.min(girth, distances[i][i]); eccentricities[i] = 0; for (int j = 0; j < distances.length; j++) { if (i != j) { eccentricities[i] = Math.max(eccentricities[i], distances[i][j]); } } } attributes.setEccentricities(eccentricities); attributes.setGirth(girth); attributes.setMaximumFragmentSizes( calculateMaximumFragmentSizes(indexMap)); // Obtain center vertices and best fragmenters for (int i = 0, r = attributes.getRadius(), s = attributes.getBestFragmentSize(); i < distances.length; i++) { if (eccentricities[i] == r) { attributes.addVertex(getVertex(i)); } if (attributes.getMaximumFragmentSizes()[i] == s) { attributes.addFragmenter(getVertex(i)); } } } private int[][] calculateDistances(HashMap indexMap) { // Calculate the adjacency matrix int n = getNumberOfVertices(); int[][] distances = new int[n][n]; for (int i = 0; i < n; i++) { int[] row = distances[i]; AtomicVertex vertex = getVertex(i); for (int j = 0; j < n; j++) { row[j] = Integer.MAX_VALUE / 2; } for (int j = 0, m = vertex.getNumberOfOutgoingArcs(); j < m; j++) { Integer index = (Integer) indexMap.get(vertex.getHeadVertex(j)); if (index != null) { row[index.intValue()] = 1; } } } // Floyd-Warshall algorithm for the distances for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (distances[i][k] + distances[k][j] < distances[i][j]) { distances[i][j] = distances[i][k] + distances[k][j]; } } } } return distances; } private HashMap calculateIndexMap() { HashMap result = new HashMap(); for (int i = 0, n = getNumberOfVertices(); i < n; i++) { result.put(getVertex(i), new Integer(i)); } return result; } private int[] calculateMaximumFragmentSizes(HashMap indexMap) { // clone graph defining this strong component AtomicVertex[] graph = new AtomicVertex[getNumberOfVertices()]; for (int i = 0; i < graph.length; i++) { graph[i] = new AtomicVertex(null); } for (int i = 0; i < graph.length; i++) { AtomicVertex vertex = getVertex(i); for (int j = 0, n = vertex.getNumberOfOutgoingArcs(); j < n; j++) { Integer index = (Integer) indexMap.get(vertex.getHeadVertex(j)); if (index != null) { graph[i].addOutgoingArcTo(graph[index.intValue()]); } } } StrongComponentProcessor processor = new StrongComponentProcessor(false); int[] maximumFragmentSizes = new int[getNumberOfVertices()]; for (int i = 0; i < maximumFragmentSizes.length; i++) { graph[i].setDefaultValueOfGraphVertexFlag(false); processor.deepSearchFirst(graph); StrongComponent[] fragments = processor.getStrongComponents(); maximumFragmentSizes[i] = 0; for (int j = 0; j < fragments.length; j++) { maximumFragmentSizes[i] = Math.max(maximumFragmentSizes[i], fragments[j].getNumberOfVertices()); } graph[i].setDefaultValueOfGraphVertexFlag(true); } return maximumFragmentSizes; } /** * Reset this component. Calls reset of the superclass. Sets the activity * flag to false and the longest walk to -1. */ public void reset() { super.reset(); _active = false; _longestWalk = -1; } public boolean isActive() { return _active; } public void setActive(boolean active) { _active = active; } public int getLongestWalk() { return _longestWalk; } public void setLongestWalk(int longestWalk) { _longestWalk = longestWalk; } public String toString() { StringBuffer result = new StringBuffer("Strong component with "); int n = getNumberOfVertices(); result.append(n).append(n > 1 ? " vertices." : " vertex."); result.append(" Longest walk: ").append(getLongestWalk()); for (int i = 0; i < n; i++) { result.append("\n ").append(getVertex(i)); } return new String(result); } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/StrongComponentAnalyser.java��������������������������������������0000664�0000000�0000000�00000006312�12021221155�0024704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.HashMap; import java.util.Map; /** * Analyser of a directed graph for finding its strong components. * * @author Franz-Josef Elmer */ public class StrongComponentAnalyser { private final AtomicVertex[] _graph; private StrongComponent[] _components; private HashMap _layerMap; /** * Creates an instance for the specified graph. */ public StrongComponentAnalyser(AtomicVertex[] graph) { _graph = graph; //Arrays.sort(_graph, null); } /** Returns the original graph. That is, the argument of the constructor. */ public AtomicVertex[] getGraph() { return _graph; } /** Returns the graph of strong components. */ public StrongComponent[] getCondensedGraph() { if (_components == null) { StrongComponentProcessor processor = new StrongComponentProcessor(true); processor.deepSearchFirst(_graph); _components = processor.getStrongComponents(); } return _components; } /** * Returns the maping of the nodes of the original graph onto a layer index * (i.e. length of the longest path of the condensed graph). * @return a map where the keys are instances of {@link AtomicVertex} * and the values are instances of <tt>Integer</tt>. */ public Map getLayerMap() { if (_layerMap == null) { StrongComponent[] components = getCondensedGraph(); new LongestWalkProcessor().deepSearchFirst(components); _layerMap = new HashMap(); for (int i = 0; i < components.length; i++) { StrongComponent component = components[i]; Integer layer = new Integer(component.getLongestWalk()); for (int j = 0, n = component.getNumberOfVertices(); j < n; j++) { _layerMap.put(component.getVertex(j), layer); } } } return _layerMap; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/StrongComponentProcessor.java�������������������������������������0000664�0000000�0000000�00000013707�12021221155�0025113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.Enumeration; import java.util.Hashtable; import java.util.Stack; import java.util.Vector; /** * A processor which extracts the strong components of a directed graph. * A strong component is a maximal strongly connected subgraph of a * directed graph. The implementation is based on Tarjan's algorithm. * * @author Franz-Josef Elmer */ public class StrongComponentProcessor extends GraphProcessor { private final boolean _calculateAttributes; private int _counter; private Stack _vertexStack = new Stack(); private Vector _strongComponents = new Vector(); private Hashtable _vertexToComponents = new Hashtable(); private StrongComponent[] _graph; /** * Creates an instance. * @param calculateAttributes If <tt>true</tt> the attributes of the * strong components will be calculated. Otherwise not. */ public StrongComponentProcessor(boolean calculateAttributes) { _calculateAttributes = calculateAttributes; } /** * Returns the result of {@link #deepSearchFirst}. */ public StrongComponent[] getStrongComponents() { return _graph; } protected void initializeProcessing(Vertex[] graph) { _counter = 0; _vertexStack.setSize(0); _strongComponents.setSize(0); _vertexToComponents.clear(); } /** * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link AtomicVertex}. */ protected void processBefore(Vertex vertex) { final AtomicVertex atomicVertex = castAsAtomicVertex(vertex); atomicVertex.setOrder(_counter); atomicVertex.setLow(_counter++); _vertexStack.push(atomicVertex); } /** * @throws IllegalArgumentException if <tt>tail</tt> and <tt>head</tt> are * not an instances of {@link AtomicVertex}. */ protected void processArc(Vertex tail, Vertex head) { final AtomicVertex t = castAsAtomicVertex(tail); final AtomicVertex h = castAsAtomicVertex(head); if (h.isGraphVertex()) { if (!h.isVisited()) { process(h); t.setLow(Math.min(t.getLow(), h.getLow())); } else if (h.getOrder() < t.getOrder() && _vertexStack.contains(h)) { t.setLow(Math.min(t.getLow(), h.getOrder())); } } } /** * Processes the specified vertex after all its outgoing arcs are * processed. * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link AtomicVertex}. */ protected void processAfter(Vertex vertex) { final AtomicVertex atomicVertex = castAsAtomicVertex(vertex); if (atomicVertex.getLow() == atomicVertex.getOrder()) { StrongComponent component = new StrongComponent(); while (!_vertexStack.isEmpty() && ((AtomicVertex) _vertexStack.peek()).getOrder() >= atomicVertex.getOrder()) { AtomicVertex vertexOfComponent = (AtomicVertex) _vertexStack.pop(); component.addVertex(vertexOfComponent); _vertexToComponents.put(vertexOfComponent, component); } _strongComponents.addElement(component); } } /** * Adds all arcs to the strong components. There is an arc from a strong * component to another one if there is at least one arc from a vertex * of one component to a vertex the other one. */ protected void finishProcessing(Vertex[] graph) { _graph = new StrongComponent[_strongComponents.size()]; for (int i = 0; i < _graph.length; i++) { _graph[i] = (StrongComponent) _strongComponents.elementAt(i); if (_calculateAttributes) { _graph[i].calculateAttributes(); } } Enumeration keys = _vertexToComponents.keys(); while (keys.hasMoreElements()) { AtomicVertex vertex = (AtomicVertex) keys.nextElement(); StrongComponent tail = (StrongComponent) _vertexToComponents.get(vertex); for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { AtomicVertex h = (AtomicVertex) vertex.getHeadVertex(i); if (h.isGraphVertex()) { StrongComponent head = (StrongComponent) _vertexToComponents.get(h); if (head != null && head != tail) { tail.addOutgoingArcTo(head); } } } } } /** * Casts the specified vertex as an {@link AtomicVertex}. * @throws IllegalArgumentException if <tt>vertex</tt> is not an instance * of {@link AtomicVertex}. */ private AtomicVertex castAsAtomicVertex(Vertex vertex) { if (vertex instanceof AtomicVertex) { return (AtomicVertex) vertex; } else { throw new IllegalArgumentException( vertex + " is not an instance of AtomicVertex"); } } } //class���������������������������������������������������������classycle-1.4/src/classycle/graph/Vertex.java�������������������������������������������������������0000664�0000000�0000000�00000013071�12021221155�0021323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; import java.util.Vector; /** * The base class for any type of vertex in a directed graph. * <p> * A <tt>Vertex</tt> holds an {@link Attributes} object which encapsulates * all properties of the vertex which are not necessary to know for * parsing a graph in a {@link GraphProcessor}. Only the visited flag will * be manipulated during parsing. * <p> * A <tt>Vertex</tt> knows the head and tail vertices of all its outgoing * and incoming arcs. When a head vertex is added by the method * {@link #addOutgoingArcTo} also the corresponding incoming arc is built * in the head vertex. The same is true the other way around. Note, * that multi-arcs are not possible. That is, adding an already added * head/tail vertex again as a head/tail vertex will be ignored. * * @author Franz-Josef Elmer */ public class Vertex implements Comparable { private final Vector _heads = new Vector(); private final Vector _tails = new Vector(); private final Attributes _attributes; private boolean _visited; /** Create a new instance for the specified attributes. */ public Vertex(Attributes attributes) { _attributes = attributes; } /** Returns the attributes. */ public Attributes getAttributes() { return _attributes; } /** * Returns the number of outgoing arcs. This is equivalent to the number * of head vertices. */ public int getNumberOfOutgoingArcs() { return _heads.size(); } /** Returns the head vertex of the specified outgoing arc. */ public Vertex getHeadVertex(int index) { return (Vertex) _heads.elementAt(index); } /** * Adds an outgoing arc to the specified vertex. Also calls * {@link #addIncomingArcTo} for <tt>headVertex</tt> with <tt>this</tt> as * the argument. Does nothing if <tt>headVertex</tt> is the head * vertex of an already existing outgoing arc. * @param headVertex Head vertex to be added to establish a new outgoing arc. * <tt>Null</tt> is not allowed. */ public void addOutgoingArcTo(Vertex headVertex) { if (!_heads.contains(headVertex)) { _heads.addElement(headVertex); headVertex.addIncomingArcTo(this); } } /** * Returns the number of incoming arcs. This is equivalent to the number * of tail vertices. */ public int getNumberOfIncomingArcs() { return _tails.size(); } /** Returns the tail vertex of the specified outgoing arc. */ public Vertex getTailVertex(int index) { return (Vertex) _tails.elementAt(index); } /** * Adds an incoming arc to the specified vertex. Also calls * {@link #addOutgoingArcTo} for <tt>tailVertex</tt> with <tt>this</tt> as * the argument. Does nothing if <tt>tailVertex</tt> is the * tail vertex of an already existing incoming arc. * @param tailVertex Tail vertex to be added to establish a new incoming arc. * <tt>Null</tt> is not allowed. */ public void addIncomingArcTo(Vertex tailVertex) { if (!_tails.contains(tailVertex)) { _tails.addElement(tailVertex); tailVertex.addOutgoingArcTo(this); } } /** Reset this vertex. That is, the visited flag is set to <tt>false</tt>. */ public void reset() { _visited = false; } /** * Marks this instance as visited. * That is, the visited flag becomes <tt>true</tt>. */ public void visit() { _visited = true; } /** Returns the visited flag. */ public boolean isVisited() { return _visited; } /** * Returns <tt>toString()</tt> of the attributes and the number of * incoming and outgoing arcs. */ public String toString() { StringBuffer result = new StringBuffer(); result.append(getAttributes() == null ? super.toString() : getAttributes().toString()) .append(": ").append(getNumberOfIncomingArcs()) .append(" incoming arc(s), ").append(getNumberOfOutgoingArcs()) .append(" outgoing arc(s)."); return new String(result); } public int compareTo(Object object) { int result = 1; if (object instanceof Vertex && _attributes != null) { result = _attributes.compareTo(((Vertex) object)._attributes); } return result; } } //class�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/graph/VertexCondition.java����������������������������������������������0000664�0000000�0000000�00000003514�12021221155�0023173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.graph; /** * Interface of classes which determine whether a {@link Vertex} * fulfills a condition or not. * * @author Franz-Josef Elmer */ public interface VertexCondition { /** * Returns <code>true</code> if the specified vertex fulfills the * condition. * @param vertex The vertex to be checked. Can be <code>null</code>. * @return <code>false</code> if <code>vertex == null</code>. */ public boolean isFulfilled(Vertex vertex); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/���������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0017706�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/AbstractStrongComponentRenderer.java���������������������������0000664�0000000�0000000�00000007153�12021221155�0027071�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import classycle.graph.AtomicVertex; import classycle.graph.GraphAttributes; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; import classycle.graph.Vertex; /** * Abstract superclass of all {@link StrongComponentRenderer}. * * @author Franz-Josef Elmer */ public abstract class AbstractStrongComponentRenderer implements StrongComponentRenderer { /** * Creates an appropriated name for the specified {@link StrongComponent}. * Usually, the name is the fully-qualified class name of the first vertex in * <tt>component</tt> extended by "et al." if <tt>component</tt> contains * more than one vertex. If <tt>component</tt> contains * only a class and its inner classes the name is the fully-qualified * class name of the outer class extended by "and inner classes". */ public static String createName(StrongComponent component) { GraphAttributes ga = (GraphAttributes) component.getAttributes(); Vertex fragmenter = ga.getBestFragmenters()[0]; String result = ((NameAttributes) fragmenter.getAttributes()).getName(); //String result = component.getVertex(0).getAttributes().toString(); if (component.getNumberOfVertices() > 1) { AtomicVertex vertex = component.getVertex(0); NameAttributes attributes = (NameAttributes) vertex.getAttributes(); String outerClass = attributes.getName(); int index = outerClass.indexOf('$'); if (index > 0) { outerClass = outerClass.substring(0, index); } boolean isInnerClass = true; for (int i = 0, n = component.getNumberOfVertices(); i < n; i++) { attributes = (NameAttributes) component.getVertex(i).getAttributes(); if (attributes.getName().equals(outerClass)) { vertex = component.getVertex(i); } else if (!attributes.getName().startsWith(outerClass) || attributes.getName().charAt(outerClass.length()) != '$') { isInnerClass = false; break; } } attributes = (NameAttributes) vertex.getAttributes(); if (isInnerClass) { result = attributes.getName() + " and inner classes"; } else { result += " et al."; } } return result; } } //class���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/AtomicVertexRenderer.java��������������������������������������0000664�0000000�0000000�00000004115�12021221155�0024653�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import classycle.graph.AtomicVertex; import classycle.graph.StrongComponent; /** * Renderer for {@link AtomicVertex AtomicVertices}. * * @author Franz-Josef Elmer */ public interface AtomicVertexRenderer { /** * Renders an {@link AtomicVertex}. * @param vertex Vertex to be rendered. * @param cycle Cycle to which <code>vertex</code> belongs. Will be * <code>null</code> if it does not belong to a cycle (i.e. * a strong component with more than one element). * @param layerIndex Index of the layer to which <code>vertex</code> * belongs. */ public String render(AtomicVertex vertex, StrongComponent cycle, int layerIndex); }���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/PlainClassRenderer.java����������������������������������������0000664�0000000�0000000�00000005532�12021221155�0024276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import classycle.ClassAttributes; import classycle.graph.AtomicVertex; import classycle.graph.StrongComponent; /** * Plain text renderer of an {@link AtomicVertex} with * {@link ClassAttributes}. * * @author Franz-Josef Elmer */ public class PlainClassRenderer implements AtomicVertexRenderer { /** * Renderes the specified vertex. It is assumed that the vertex attributes * are of the type {@link classycle.ClassAttributes}. * @param vertex Vertex to be rendered. * @return the rendered vertex. */ public String render(AtomicVertex vertex, StrongComponent cycle, int layerIndex) { if (vertex.getAttributes() instanceof ClassAttributes) { int usesInternal = 0; int usesExternal = 0; for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { if (((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex()) { usesInternal++; } else { usesExternal++; } } StringBuffer result = new StringBuffer(vertex.getAttributes().toString()); result.append(": Used by ").append(vertex.getNumberOfIncomingArcs()) .append(" classes. Uses ").append(usesInternal).append('/') .append(usesExternal).append(" internal/external classes"); return new String(result); } throw new IllegalArgumentException( "Missing class attributes in vertex " + vertex); } } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/PlainStrongComponentRenderer.java������������������������������0000664�0000000�0000000�00000004646�12021221155�0026375�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import classycle.graph.StrongComponent; /** * Plain text renderer of a {@link StrongComponent}. * * @author Franz-Josef Elmer */ public class PlainStrongComponentRenderer extends AbstractStrongComponentRenderer { public String render(StrongComponent component) { AtomicVertexRenderer classRenderer = new PlainClassRenderer(); StringBuffer result = new StringBuffer(); int n = component.getNumberOfVertices(); if (n == 1) { result.append(classRenderer.render(component.getVertex(0), null, 0)) .append(". Layer: ").append(component.getLongestWalk()); } else { result.append("Cycle: ").append(createName(component)).append(" with ") .append(n).append(" vertices.") .append(" Layer: ").append(component.getLongestWalk()); for (int i = 0; i < n; i++) { result.append("\n ") .append(classRenderer.render(component.getVertex(i), null, 0)); } } return new String(result); } } //class������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/StrongComponentRenderer.java�����������������������������������0000664�0000000�0000000�00000003266�12021221155�0025406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import classycle.graph.StrongComponent; /** * Interface for rendering a {@link StrongComponent}. * * @author Franz-Josef Elmer */ public interface StrongComponentRenderer { /** Renderes the specified {@link StrongComponent}. */ public String render(StrongComponent component); } //interface������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/TemplateBasedClassRenderer.java��������������������������������0000664�0000000�0000000�00000010453�12021221155�0025743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import java.text.MessageFormat; import classycle.ClassAttributes; import classycle.NameAndSourceAttributes; import classycle.graph.AtomicVertex; import classycle.graph.StrongComponent; /** * Renderer of an {@link AtomicVertex} with * {@link ClassAttributes}. The renderer is based on a * <tt>java.text.MessageFormat</tt> template. The variables in the * template have the following meaning: * <table border=1 cellpadding=5> * <tr><th>Variable index</th><th>Description</th></tr> * <tr><td>0</td><td>fully-qualified class name</td></tr> * <tr><td>1</td><td>class type</td></tr> * <tr><td>2</td><td>size of the class file in bytes</td></tr> * <tr><td>3</td> * <td><tt>true</tt> if inner class otherwise <tt>false</tt></td></tr> * <tr><td>4</td><td>Number of incoming arcs</td></tr> * <tr><td>5</td> * <td>Number of outgoing arcs to other vertices in the graph</td></tr> * <tr><td>6</td><td>Number of outgoing arcs to external vertices</td></tr> * <tr><td>7</td><td>Layer index</td></tr> * <tr><td>8</td><td>Name of the cycle or empty string</td></tr> * <tr><td>9</td><td>Source of class file if known</td></tr> * </table> * * @author Franz-Josef Elmer */ public class TemplateBasedClassRenderer implements AtomicVertexRenderer { private MessageFormat _format; /** Creates an instance for the specified template. */ public TemplateBasedClassRenderer(String template) { _format = new MessageFormat(template); } /** * Renderes the specified vertex. It is assumed that the vertex attributes * are of the type {@link classycle.ClassAttributes}. * @param vertex Vertex to be rendered. * @return the rendered vertex. */ public String render(AtomicVertex vertex, StrongComponent cycle, int layerIndex) { String[] values = new String[10]; NameAndSourceAttributes attributes = (NameAndSourceAttributes) vertex.getAttributes(); values[0] = attributes.getName(); values[2] = Integer.toString(attributes.getSize()); values[9] = attributes.getSources(); if (attributes instanceof ClassAttributes) { ClassAttributes ca = (ClassAttributes) attributes; values[1] = ca.getType(); values[3] = ca.isInnerClass() ? "true" : "false"; } else { values[1] = ""; values[3] = ""; } values[4] = Integer.toString(vertex.getNumberOfIncomingArcs()); int usesInternal = 0; int usesExternal = 0; for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { if (((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex()) { usesInternal++; } else { usesExternal++; } } values[5] = Integer.toString(usesInternal); values[6] = Integer.toString(usesExternal); values[7] = Integer.toString(layerIndex); values[8] = cycle == null ? "" : AbstractStrongComponentRenderer.createName(cycle); return _format.format(values); } }���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/TemplateBasedStrongComponentRenderer.java����������������������0000664�0000000�0000000�00000005236�12021221155�0030040�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import java.text.MessageFormat; import classycle.graph.StrongComponent; /** * Renderer of a {@link StrongComponent}. The renderer is based on a * <tt>java.text.MessageFormat</tt> template. * * @author Franz-Josef Elmer */ public class TemplateBasedStrongComponentRenderer extends AbstractStrongComponentRenderer { private final MessageFormat _format; private final int _minimumNumber; /** * Creates an instance for the specified template. * @param template The template. * @param minimumSize Minimum number of vertices the {@link StrongComponent} * should have to be rendered. */ public TemplateBasedStrongComponentRenderer(String template, int minimumNumber) { _format = new MessageFormat(template); _minimumNumber = minimumNumber; } public String render(StrongComponent component) { String result = ""; if (component.getNumberOfVertices() >= _minimumNumber) { String[] values = new String[3]; values[0] = createName(component); values[1] = Integer.toString(component.getNumberOfVertices()); values[2] = Integer.toString(component.getLongestWalk()); result = _format.format(values); } return result; } } //class������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/XMLAtomicVertexRenderer.java�����������������������������������0000664�0000000�0000000�00000006320�12021221155�0025234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import java.text.MessageFormat; import classycle.graph.AtomicVertex; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; /** * XML renderer of an {@link AtomicVertex} with * {@link NameAttributes}. * * @author Franz-Josef Elmer */ public abstract class XMLAtomicVertexRenderer implements AtomicVertexRenderer { /** * Renderes the specified vertex. It is assumed that the vertex attributes * are of the type {@link classycle.ClassAttributes}. * @return the rendered vertex. */ public String render(AtomicVertex vertex, StrongComponent cycle, int layerIndex) { StringBuffer result = new StringBuffer(); result.append(getVertexRenderer().render(vertex, cycle, layerIndex)); MessageFormat format = new MessageFormat(" <" + getRefElement() + " name=\"{0}\"" + " type=\"{1}\"/>\n"); String[] values = new String[2]; for (int i = 0, n = vertex.getNumberOfIncomingArcs(); i < n; i++) { values[0] = ((NameAttributes) vertex.getTailVertex(i).getAttributes()) .getName(); values[1] = "usedBy"; format.format(values, result, null); } for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { values[0] = ((NameAttributes) vertex.getHeadVertex(i).getAttributes()) .getName(); values[1] = ((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex() ? "usesInternal" : "usesExternal"; format.format(values, result, null); } result.append(" </").append(getElement()).append(">\n"); return new String(result); } protected abstract AtomicVertexRenderer getVertexRenderer(); protected abstract String getElement(); protected abstract String getRefElement(); } //class����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/XMLClassRenderer.java������������������������������������������0000664�0000000�0000000�00000004040�12021221155�0023664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; /** * XML renderer of an {@link AtomicVertex} with * {@link ClassAttributes}. * * @author Franz-Josef Elmer */ public class XMLClassRenderer extends XMLAtomicVertexRenderer { protected String getElement() { return "class"; } protected String getRefElement() { return "classRef"; } protected AtomicVertexRenderer getVertexRenderer() { return new TemplateBasedClassRenderer(" <" + getElement() + " name=\"{0}\" sources=\"{9}\" type=\"{1}\" innerClass=\"{3}\"" + " size=\"{2}\" usedBy=\"{4}\" usesInternal=\"{5}\"" + " usesExternal=\"{6}\" layer=\"{7}\" cycle=\"{8}\">\n"); } } //class������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/renderer/XMLStrongComponentRenderer.java��������������������������������0000664�0000000�0000000�00000013703�12021221155�0025764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.renderer; import java.text.MessageFormat; import classycle.graph.GraphAttributes; import classycle.graph.NameAttributes; import classycle.graph.StrongComponent; import classycle.graph.Vertex; /** * XML renderer of a {@link StrongComponent}. * * @author Franz-Josef Elmer */ public class XMLStrongComponentRenderer extends AbstractStrongComponentRenderer { private final int _minimumSize; protected String getStrongComponentElementName() { return "cycle"; } protected String getNodesElementName() { return "classes"; } protected String getNodeElementName() { return "classRef"; } protected String getCenterNodesElementName() { return "centerClasses"; } protected String getBestFragmentersElementName() { return "bestFragmenters"; } private MessageFormat getStrongComponentElementTemplate() { return new MessageFormat(" <" + getStrongComponentElementName() + " name=\"{0}\" size=\"{1}\" longestWalk=\"{2}\"" + " girth=\"{3}\" radius=\"{4}\" diameter=\"{5}\"" + " bestFragmentSize=\"{6}\">\n"); } private MessageFormat getNodeElementTemplate() { return new MessageFormat(" <" + getNodeElementName() + " name=\"{0}\"/>\n"); } private MessageFormat getNodeElementTemplateWithEccentricity() { return new MessageFormat(" <" + getNodeElementName() + " name=\"{0}\" eccentricity=\"{1}\"" + " maximumFragmentSize=\"{2}\"/>\n"); } /** * Creates an instance for the specified minimum number vertices. * @param minimumSize Minimum number of vertices the {@link StrongComponent} * should have to be rendered. */ public XMLStrongComponentRenderer(int minimumSize) { _minimumSize = minimumSize; } public String render(StrongComponent component) { StringBuffer result = new StringBuffer(); if (component.getNumberOfVertices() >= _minimumSize) { String[] values = new String[7]; values[0] = createName(component); values[1] = Integer.toString(component.getNumberOfVertices()); values[2] = Integer.toString(component.getLongestWalk()); GraphAttributes attributes = (GraphAttributes) component.getAttributes(); values[3] = Integer.toString(attributes.getGirth()); values[4] = Integer.toString(attributes.getRadius()); values[5] = Integer.toString(attributes.getDiameter()); values[6] = Integer.toString(attributes.getBestFragmentSize()); getStrongComponentElementTemplate().format(values, result, null); renderClasses(component, result); renderVertices(attributes.getCenterVertices(), result, getCenterNodesElementName()); renderVertices(attributes.getBestFragmenters(), result, getBestFragmentersElementName()); result.append(" </").append(getStrongComponentElementName()) .append(">\n"); } return new String(result); } private void renderClasses(StrongComponent component, StringBuffer result) { result.append(" <").append(getNodesElementName()).append(">\n"); int[] eccentricities = ((GraphAttributes) component.getAttributes()).getEccentricities(); int[] maximumFragmentSizes = ((GraphAttributes) component.getAttributes()) .getMaximumFragmentSizes(); String[] values = new String[3]; MessageFormat template = getNodeElementTemplateWithEccentricity(); for (int i = 0, n = component.getNumberOfVertices(); i < n; i++) { values[0] = ((NameAttributes) component.getVertex(i).getAttributes()) .getName(); values[1] = Integer.toString(eccentricities[i]); values[2] = Integer.toString(maximumFragmentSizes[i]); template.format(values, result, null); } result.append(" </").append(getNodesElementName()).append(">\n"); } private void renderVertices(Vertex[] vertices, StringBuffer result, String tagName) { result.append(" <").append(tagName).append(">\n"); String[] values = new String[1]; MessageFormat template = getNodeElementTemplate(); for (int i = 0; i < vertices.length; i++) { values[0] = ((NameAttributes) vertices[i].getAttributes()).getName(); template.format(values, result, null); } result.append(" </").append(tagName).append(">\n"); } } //class�������������������������������������������������������������classycle-1.4/src/classycle/util/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0017055�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/AndStringPattern.java����������������������������������������������0000664�0000000�0000000�00000004271�12021221155�0023153�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; /** * Logical AND Operation on a sequence of {@link StringPattern StringPatterns}. * * @author Franz-Josef Elmer */ public class AndStringPattern extends StringPatternSequence { /** * Creates instance with specified patterns. */ public AndStringPattern(StringPattern... pattern) { super(pattern); } /** * Return <code>false</code> if a pattern in the sequence returns * <code>false</code>. Otherwise <code>true</code> is returned. */ public boolean matches(String string) { boolean result = true; for (int i = 0, n = _patterns.size(); i < n; i++) { if (!((StringPattern) _patterns.get(i)).matches(string)) { result = false; break; } } return result; } protected String getOperatorSymbol() { return " & "; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/NotStringPattern.java����������������������������������������������0000664�0000000�0000000�00000004452�12021221155�0023212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; /** * Logical NOT operation on the result of a wrapped {@link StringPattern}. * * @author Franz-Josef Elmer */ public class NotStringPattern implements StringPattern { private final StringPattern _pattern; /** * Creates an instance based on the specified pattern. * @param pattern Pattern who's matching result will be negate. * Must be not <tt>null</tt>. */ public NotStringPattern(StringPattern pattern) { _pattern = pattern; } /** * Returns <tt>true</tt> if the wrapped {@link StringPattern} returns * <tt>false</tt> and vice-versa. */ public boolean matches(String string) { return !_pattern.matches(string); } public String toString() { String expression = _pattern.toString(); boolean bracketsNeeded = expression.startsWith("(") == false && expression.indexOf(' ') > 0; return '!' + (bracketsNeeded ? '(' + expression + ')' : expression); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/OrStringPattern.java�����������������������������������������������0000664�0000000�0000000�00000004261�12021221155�0023030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; /** * Logical OR Operation on a sequence of {@link StringPattern StringPatterns}. * * @author Franz-Josef Elmer */ public class OrStringPattern extends StringPatternSequence { /** * Creates instance with specified patterns. */ public OrStringPattern(StringPattern... pattern) { super(pattern); } /** * Return <code>true</code> if a pattern in the sequence returns * <code>true</code>. Otherwise <code>false</code> is returned. */ public boolean matches(String string) { boolean result = false; for (int i = 0, n = _patterns.size(); i < n; i++) { if (((StringPattern) _patterns.get(i)).matches(string)) { result = true; break; } } return result; } protected String getOperatorSymbol() { return " "; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/StringPattern.java�������������������������������������������������0000664�0000000�0000000�00000003271�12021221155�0022527�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; /** * Interface for string pattern matching. * * @author Franz-Josef Elmer */ public interface StringPattern { /** * Returns <tt>true</tt> if the specified string matches the pattern. * @param string String to be matched. Can be <tt>null</tt>. */ public boolean matches(String string); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/StringPatternSequence.java�����������������������������������������0000664�0000000�0000000�00000005171�12021221155�0024221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Sequence of {@link StringPattern StringPatterns}. * * @author Franz-Josef Elmer */ public abstract class StringPatternSequence implements StringPattern { protected final List<StringPattern> _patterns = new ArrayList<StringPattern>(); protected StringPatternSequence(StringPattern[] pattern) { _patterns.addAll(Arrays.asList(pattern)); } /** * Appends the specified pattern. */ public void appendPattern(StringPattern pattern) { _patterns.add(pattern); } public String toString() { StringBuffer buffer = new StringBuffer(); int size = _patterns.size(); String operatorSymbol = getOperatorSymbol(); boolean bracketsNeeded = size > 1 && operatorSymbol.equals(" & "); if (bracketsNeeded) { buffer.append('('); } for (int i = 0; i < size; i++) { if (i != 0) { buffer.append(operatorSymbol); } buffer.append(_patterns.get(i)); } return new String(bracketsNeeded ? buffer.append(')') : buffer); } /** * Returns the operator symbol for pretty printing. Needed by * <code>toString()</code>. */ protected abstract String getOperatorSymbol(); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/Text.java����������������������������������������������������������0000664�0000000�0000000�00000006052�12021221155�0020647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; /** * Collection of useful static method concerning string manipulation. * * @author Franz-Josef Elmer */ public class Text { private static final String ESCAPE_CHARACTERS = "<>&\"'"; private static final String[] ESCAPE_SEQUENCES = new String[] { "<", ">", "&", """, "'"}; private Text() {} /** * Escapes special XML characters in the specified text. * @param text Text to be escaped. Must be not <tt>null</tt>. * @return copy of the text where the special XML characters has been * replaced by the escape sequences. */ public static String excapeForXML(String text) { StringBuffer buffer = new StringBuffer(); for (int i = 0, n = text.length(); i < n; i++) { char c = text.charAt(i); int index = ESCAPE_CHARACTERS.indexOf(c); if (index < 0) { buffer.append(c); } else { buffer.append(ESCAPE_SEQUENCES[index]); } } return new String(buffer); } /** * Reads multi-line text from the specified file. * @param file Text file. * @return read text file with standard Java newline characters. * @throws IOException if some reading error occurs. */ public static String readTextFile(File file) throws IOException { StringBuffer buffer = new StringBuffer(); BufferedReader reader = new BufferedReader(new FileReader(file)); String line; while ((line = reader.readLine()) != null) { buffer.append(line).append('\n'); } String result = new String(buffer); return result; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/TrueStringPattern.java���������������������������������������������0000664�0000000�0000000�00000003336�12021221155�0023371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; /** * String pattern which return <tt>true</tt> in any case. * * @author Franz-Josef Elmer */ public class TrueStringPattern implements StringPattern { /** Returns <code>true</code> independent of the argument. */ public boolean matches(String string) { return true; } public String toString() { return "true"; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/src/classycle/util/WildCardPattern.java�����������������������������������������������0000664�0000000�0000000�00000012026�12021221155�0022750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package classycle.util; import java.util.StringTokenizer; /** * Wildcard string pattern matching class. Only '*' is interpreted as wild card * meaning the occurance of any number of arbitray characters. * <p> * This is a thread-safe immutable class. * <p> * Example: The code snippet * <pre><tt> * StringPattern pattern = new WildCardPattern("Hello*"); * System.out.println(pattern.matches("Hello world!")); * System.out.println(pattern.matches("Hi Jim!")); * </tt></pre> * will produce the output * <pre><tt> * true * false * </tt></pre> * * @author Franz-Josef Elmer */ public class WildCardPattern implements StringPattern { private static final String WILD_CARD = "*"; /** * Returns a {@link StringPattern} object based on a sequences of * wild-card patterns separated by the specified delimiter characters. * The return object matches a string if at least one of the * wild-card pattern matches. * @param patterns Wild-card patterns separated by delimiters defined * in <tt>delimiters</tt>. The actual pattern will be trimed. * That is, leading and trailing white-space characters are removed. * @param delimiters Recognized delimiters. * @return */ public static StringPattern createFromsPatterns(String patterns, String delimiters) { if (delimiters.indexOf(WILD_CARD) >= 0) { throw new IllegalArgumentException("No wild card '" + WILD_CARD + "' are allowed as delimiters: " + delimiters); } OrStringPattern result = new OrStringPattern(); StringTokenizer tokenizer = new StringTokenizer(patterns, delimiters); while (tokenizer.hasMoreTokens()) { result.appendPattern(new WildCardPattern(tokenizer.nextToken().trim())); } return result; } private final String _pattern; private final String[] _constantParts; private final boolean _startsWithAnything; private final boolean _endsWithAnything; /** * Creates an instance based on the specified pattern. * @param pattern Pattern which may contain '*' wildcard characters. * Must be not <tt>null</tt>. */ public WildCardPattern(String pattern) { _pattern = pattern; _startsWithAnything = pattern.startsWith(WILD_CARD); _endsWithAnything = pattern.endsWith(WILD_CARD); StringTokenizer tokenizer = new StringTokenizer(pattern, WILD_CARD); _constantParts = new String[tokenizer.countTokens()]; for (int i = 0; i < _constantParts.length; i++) { _constantParts[i] = tokenizer.nextToken(); } } /** * Returns the pattern as delivered to the constructor. */ public String toString() { return _pattern; } /** * @return <tt>false</tt> if <tt>string == null</tt>. */ public boolean matches(String string) { return string == null ? false : matches(string, 0, 0); } private boolean matches(String string, int indexInString, int indexInConstantParts) { boolean result = true; if (indexInConstantParts < _constantParts.length) { String constantPart = _constantParts[indexInConstantParts]; do { int index = string.indexOf(constantPart, indexInString); if (index < 0 || (indexInString == 0 && !_startsWithAnything && index > 0)) { result = false; break; } indexInString = index + constantPart.length(); result = matches(string, indexInString, indexInConstantParts + 1); } while (result == false); } else { result = result && (_endsWithAnything || indexInString == string.length()); } return result; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0014756�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0016740�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/AnalyserCommandLineTest.java����������������������������������������0000664�0000000�0000000�00000010136�12021221155�0024331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 07.07.2004 */ package classycle; import classycle.util.StringPattern; import junit.framework.TestCase; /** * @author Franz-Josef Elmer */ public class AnalyserCommandLineTest extends TestCase { public void testNoOptionsNoClasses() { AnalyserCommandLine commandLine = new AnalyserCommandLine(new String[0]); assertFalse(commandLine.isValid()); assertEquals(0, commandLine.getClassFiles().length); } public void testNoOptions() { AnalyserCommandLine commandLine = new AnalyserCommandLine(new String[] {"bla"}); checkNoOptions(commandLine); assertEquals(1, commandLine.getClassFiles().length); assertEquals("bla", commandLine.getClassFiles()[0]); assertEquals("bla", commandLine.getTitle()); commandLine = new AnalyserCommandLine(new String[] {"bla", "foo.jar"}); checkNoOptions(commandLine); assertEquals(2, commandLine.getClassFiles().length); assertEquals("bla", commandLine.getClassFiles()[0]); assertEquals("foo.jar", commandLine.getClassFiles()[1]); assertEquals("bla", commandLine.getTitle()); } private void checkNoOptions(AnalyserCommandLine commandLine) { assertFalse(commandLine.isRaw()); assertFalse(commandLine.isStrong()); assertFalse(commandLine.isPackagesOnly()); assertFalse(commandLine.isCycles()); assertNull(commandLine.getCsvFile()); assertNull(commandLine.getXmlFile()); StringPattern pattern = commandLine.getPattern(); assertTrue(pattern.matches("blabla")); assertTrue(commandLine.isValid()); } public void testOptionsNoClasses() { AnalyserCommandLine commandLine = new AnalyserCommandLine(new String[] {"-raw"}); assertFalse(commandLine.isValid()); assertEquals(0, commandLine.getClassFiles().length); commandLine = new AnalyserCommandLine(new String[] {"-raw", "-title=42"}); assertFalse(commandLine.isValid()); assertEquals(0, commandLine.getClassFiles().length); } public void testOptionTitle() { AnalyserCommandLine commandLine = new AnalyserCommandLine(new String[] {"-title=42", "foo.jar"}); assertTrue(commandLine.isValid()); assertEquals(1, commandLine.getClassFiles().length); assertEquals("foo.jar", commandLine.getClassFiles()[0]); assertEquals("42", commandLine.getTitle()); } public void testOptionIncludingClasses() { AnalyserCommandLine commandLine = new AnalyserCommandLine( new String[] {"-includingClasses=foo*,*la", "foo.jar"}); assertTrue(commandLine.isValid()); assertEquals(1, commandLine.getClassFiles().length); assertEquals("foo.jar", commandLine.getClassFiles()[0]); assertEquals("foo.jar", commandLine.getTitle()); StringPattern pattern = commandLine.getPattern(); checkPattern(pattern, true, new String[] {"foo", "foo.jar", "foola", "bla"}); checkPattern(pattern, false, new String[] {"bla.jar", "fo"}); } public void testOptionExcludingClasses() { AnalyserCommandLine commandLine = new AnalyserCommandLine( new String[] {"-excludingClasses=foo*,*la", "foo.jar"}); assertTrue(commandLine.isValid()); StringPattern pattern = commandLine.getPattern(); checkPattern(pattern, false, new String[] {"foo", "foo.jar", "foola", "bla"}); checkPattern(pattern, true, new String[] {"bla.jar", "fo"}); } public void testOptionIncludingExcludingClasses() { AnalyserCommandLine commandLine = new AnalyserCommandLine( new String[] {"-includingClasses=foo*", "-excludingClasses=*la"}); StringPattern pattern = commandLine.getPattern(); checkPattern(pattern, true, new String[] {"foo", "foo.jar"}); checkPattern(pattern, false, new String[] {"foola", "bla"}); } private void checkPattern(StringPattern pattern, boolean expectedMatchResult, String[] examples) { for (int i = 0; i < examples.length; i++) { assertTrue(examples[i] + " match " + expectedMatchResult, pattern.matches(examples[i]) == expectedMatchResult); } } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ClassNameExtractorTest.java�����������������������������������������0000664�0000000�0000000�00000006310�12021221155�0024205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle; import java.util.Set; import junit.framework.TestCase; import classycle.classfile.UTF8Constant; public class ClassNameExtractorTest extends TestCase { public void testIsValid() { assertEquals(true, ClassNameExtractor.isValid("java.lang.String")); assertEquals(true, ClassNameExtractor.isValid("name")); assertEquals(true, ClassNameExtractor.isValid("$name")); assertEquals(true, ClassNameExtractor.isValid("_name")); assertEquals(true, ClassNameExtractor.isValid("_name12")); assertEquals(false, ClassNameExtractor.isValid("")); assertEquals(false, ClassNameExtractor.isValid("9")); assertEquals(false, ClassNameExtractor.isValid("a.")); assertEquals(false, ClassNameExtractor.isValid("a..a")); } public void testParseUTF8Constant() { parseAndCheck("[]", "(Lb;)"); parseAndCheck("[java.util.List]", "(Ljava/util/List;)V"); parseAndCheck("[java.lang.Long, java.lang.Class, java.lang.Short]", "(Ljava/lang/Long;Ljava/lang/Class;)Ljava/lang/Short;"); parseAndCheck("[java.util.Set, java.util.List]", "<X::Ljava/util/Set<TT;>;>(Ljava/util/List<+[TX;>;)TX;"); parseAndCheck("[java.util.List]", "([[Ljava/util/List;)V"); parseAndCheck("[java.util.List, java.lang.Number]", "(Ljava/util/List<Ljava/lang/Number;>;)V"); parseAndCheck("[java.util.List, java.util.Map, java.lang.Integer, " + "java.lang.Number]", "(Ljava/util/List<Ljava/util/Map" + "<Ljava/lang/Integer;Ljava/lang/Number;>;>;)V"); parseAndCheck("[java.util.List, java.util.Map, java.lang.Integer, " + "java.lang.Number]", "(Ljava/util/List<Ljava/util/Map" + "<Ljava/lang/Integer;[Ljava/lang/Number;>;>;)V"); parseAndCheck("[java.util.List, java.util.Map, java.lang.Integer]", "(Ljava/util/List<Ljava/util/Map<Ljava/lang/Integer;[I>;>;)V"); parseAndCheck("[java.util.List, java.util.Map, java.lang.Integer, " + "java.util.Stack]", "([[Ljava/util/List<[Ljava/util/Map" + "<Ljava/lang/Integer;[Ljava/util/Stack;>;>;)V"); parseAndCheck("[java.util.List]", "(Ljava/util/List<*>;)V"); parseAndCheck("[java.util.Map, java.lang.Integer, java.lang.Number]", "(Ljava/util/Map<Ljava/lang/Integer;+Ljava/lang/Number;>;)V"); parseAndCheck("[java.util.Map, java.lang.Number]", "(Ljava/util/Map<*+Ljava/lang/Number;>;)V"); parseAndCheck("[java.lang.Object, java.util.Collection, java.lang.Short]", "Ljava/lang/Object;Ljava/util/Collection<Ljava/lang/Short;>;"); parseAndCheck("[java.util.Set, java.lang.Boolean, java.lang.Object, " + "java.util.Collection, java.lang.Short]", "<T::Ljava/util/Set<Ljava/lang/Boolean;>;>" + "Ljava/lang/Object;Ljava/util/Collection" + "<Ljava/lang/Short;>;"); } private void parseAndCheck(String expectedList, String constant) { Set names = new ClassNameExtractor(new UTF8Constant(null, constant)).extract(); assertEquals(expectedList, names.toString()); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/GraphBuilderTest.java�����������������������������������������������0000664�0000000�0000000�00000007600�12021221155�0023016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import classycle.graph.AtomicVertex; import junit.framework.TestCase; public class GraphBuilderTest extends TestCase { public void testTwoClassesWithSameNameButDifferentSources() { UnresolvedNode[] nodes = createNodes("a:s1:A -> b c a; a:s2 -> b d"); AtomicVertex[] graph = GraphBuilder.createGraph(nodes, false); assertEquals(1, graph.length); ClassAttributes attributes = (ClassAttributes) graph[0].getAttributes(); assertEquals("a", attributes.getName()); assertEquals("s1, s2", attributes.getSources()); assertEquals(2, attributes.getSize()); assertEquals(ClassAttributes.CLASS, attributes.getType()); } public void testTwoClassesWithSameNameOneWithSourceOneWithoutSource() { UnresolvedNode[] nodes = createNodes("a:s1 -> b c a; a: :A -> b d"); AtomicVertex[] graph = GraphBuilder.createGraph(nodes, false); assertEquals(1, graph.length); ClassAttributes attributes = (ClassAttributes) graph[0].getAttributes(); assertEquals("a", attributes.getName()); assertEquals("s1", attributes.getSources()); assertEquals(2, attributes.getSize()); assertEquals(ClassAttributes.ABSTRACT_CLASS, attributes.getType()); } public void testSupressedMergingOfInnerclasses() { UnresolvedNode[] nodes = createNodes("a:s:A -> b c a$1; a$1:s -> b d"); AtomicVertex[] graph = GraphBuilder.createGraph(nodes, false); assertEquals(2, graph.length); AtomicVertex node = graph[0]; assertEquals(3, node.getNumberOfOutgoingArcs()); assertEquals(0, node.getNumberOfIncomingArcs()); ClassAttributes attributes = (ClassAttributes) node.getAttributes(); assertEquals("a", attributes.getName()); node = graph[1]; assertEquals(2, node.getNumberOfOutgoingArcs()); assertEquals(1, node.getNumberOfIncomingArcs()); attributes = (ClassAttributes) node.getAttributes(); assertEquals("a$1", attributes.getName()); } public void testMergingOfInnerclasses() { UnresolvedNode[] nodes = createNodes("a:s:A -> b c a$1; a$1:s -> b d"); AtomicVertex[] graph = GraphBuilder.createGraph(nodes, true); assertEquals(1, graph.length); AtomicVertex node = graph[0]; assertEquals(3, node.getNumberOfOutgoingArcs()); assertEquals(0, node.getNumberOfIncomingArcs()); ClassAttributes attributes = (ClassAttributes) node.getAttributes(); assertEquals("a", attributes.getName()); assertEquals(4, attributes.getSize()); assertEquals(ClassAttributes.ABSTRACT_CLASS, attributes.getType()); } private UnresolvedNode[] createNodes(String description) { List nodes = new ArrayList(); StringTokenizer tokenizer = new StringTokenizer(description, ";"); while (tokenizer.hasMoreTokens()) { nodes.add(createNode(tokenizer.nextToken().trim())); } return (UnresolvedNode[]) nodes.toArray(new UnresolvedNode[nodes.size()]); } private UnresolvedNode createNode(String description) { UnresolvedNode node = new UnresolvedNode(); int indexOfArrow = description.indexOf("->"); String links = description.substring(indexOfArrow + 2).trim(); StringTokenizer tokenizer = new StringTokenizer(links); while (tokenizer.hasMoreTokens()) { node.addLinkTo(tokenizer.nextToken()); } String attributes = description.substring(0, indexOfArrow).trim(); tokenizer = new StringTokenizer(attributes, ":"); String name = tokenizer.nextToken(); String source = tokenizer.nextToken().trim(); if (source.length() == 0) { source = null; } boolean a = tokenizer.hasMoreTokens() && "A".equals(tokenizer.nextToken()); String type = a ? ClassAttributes.ABSTRACT_CLASS : ClassAttributes.CLASS; node.setAttributes(new ClassAttributes(name, source, type, name.length())); return node; } } ��������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/PackageProcessorTest.java�������������������������������������������0000664�0000000�0000000�00000010440�12021221155�0023675�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle; import junit.framework.TestCase; import classycle.graph.AtomicVertex; import classycle.graph.Vertex; public class PackageProcessorTest extends TestCase { private AtomicVertex _a; private AtomicVertex _b; private AtomicVertex _c; private AtomicVertex _d; private AtomicVertex _o; private AtomicVertex[] _graph; protected void setUp() throws Exception { _a = new AtomicVertex(ClassAttributes.createClass("p.A", "s", 1)); _b = new AtomicVertex(ClassAttributes.createClass("q.B", "r", 2)); _c = new AtomicVertex(ClassAttributes.createClass("q.C", "s", 3)); _d = new AtomicVertex(ClassAttributes.createClass("p.D", "s", 4)); _o = new AtomicVertex(ClassAttributes.createClass("lang.Object", "s", 42)); _o.setDefaultValueOfGraphVertexFlag(false); _a.addOutgoingArcTo(_o); _a.addOutgoingArcTo(_b); _b.addOutgoingArcTo(_o); _c.addOutgoingArcTo(_o); _c.addOutgoingArcTo(_d); _d.addOutgoingArcTo(_o); _graph = new AtomicVertex[] {_a, _b, _c, _d}; } public void testClassBExcluded() { _b.setDefaultValueOfGraphVertexFlag(false); PackageProcessor processor = new PackageProcessor(); processor.deepSearchFirst(_graph); AtomicVertex[] packageGraph = processor.getGraph(); assertEquals(2, packageGraph.length); AtomicVertex p = packageGraph[0]; assertEquals(true, p.isGraphVertex()); PackageAttributes attributes = (PackageAttributes) p.getAttributes(); assertEquals("p", attributes.getName()); assertEquals("s", attributes.getSources()); assertEquals(2, attributes.getSize()); assertEquals(1, p.getNumberOfOutgoingArcs()); Vertex packageLang = p.getHeadVertex(0); assertEquals("lang", ((PackageAttributes) packageLang.getAttributes()).getName()); AtomicVertex q = packageGraph[1]; assertEquals(true, q.isGraphVertex()); attributes = (PackageAttributes) q.getAttributes(); assertEquals("q", attributes.getName()); assertEquals("r, s", attributes.getSources()); assertEquals(2, attributes.getSize()); assertEquals(2, q.getNumberOfOutgoingArcs()); assertSame(packageLang, q.getHeadVertex(0)); assertSame(p, q.getHeadVertex(1)); } public void testClassDExcluded() { _d.setDefaultValueOfGraphVertexFlag(false); PackageProcessor processor = new PackageProcessor(); processor.deepSearchFirst(_graph); AtomicVertex[] packageGraph = processor.getGraph(); assertEquals(2, packageGraph.length); AtomicVertex q = packageGraph[1]; assertEquals(true, q.isGraphVertex()); PackageAttributes attributes = (PackageAttributes) q.getAttributes(); assertEquals("q", attributes.getName()); assertEquals(2, attributes.getSize()); assertEquals(1, q.getNumberOfOutgoingArcs()); Vertex packageLang = q.getHeadVertex(0); assertEquals("lang", ((PackageAttributes) packageLang.getAttributes()).getName()); AtomicVertex p = packageGraph[0]; assertEquals(true, p.isGraphVertex()); attributes = (PackageAttributes) p.getAttributes(); assertEquals("p", attributes.getName()); assertEquals(2, attributes.getSize()); assertEquals(2, p.getNumberOfOutgoingArcs()); assertSame(packageLang, p.getHeadVertex(0)); assertSame(q, p.getHeadVertex(1)); } public void testClassBAndCExcluded() { _b.setDefaultValueOfGraphVertexFlag(false); _c.setDefaultValueOfGraphVertexFlag(false); PackageProcessor processor = new PackageProcessor(); processor.deepSearchFirst(_graph); AtomicVertex[] packageGraph = processor.getGraph(); assertEquals(1, packageGraph.length); AtomicVertex p = packageGraph[0]; assertEquals(true, p.isGraphVertex()); PackageAttributes attributes = (PackageAttributes) p.getAttributes(); assertEquals("p", attributes.getName()); assertEquals(2, attributes.getSize()); assertEquals(2, p.getNumberOfOutgoingArcs()); AtomicVertex packageLang = (AtomicVertex) p.getHeadVertex(0); assertEquals("lang", ((PackageAttributes) packageLang.getAttributes()).getName()); assertEquals(false, packageLang.isGraphVertex()); AtomicVertex q = (AtomicVertex) p.getHeadVertex(1); assertEquals("q", ((PackageAttributes) q.getAttributes()).getName()); assertEquals(false, q.isGraphVertex()); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ParserTest.java�����������������������������������������������������0000664�0000000�0000000�00000020577�12021221155�0021712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.Arrays; import java.util.HashSet; import junit.framework.TestCase; import classycle.graph.AtomicVertex; import classycle.graph.NameAttributes; import classycle.graph.Vertex; import classycle.util.StringPattern; import classycle.util.TrueStringPattern; import classycle.util.WildCardPattern; import com.sun.tools.javac.Main; /** * * * @author Franz-Josef Elmer */ public class ParserTest extends TestCase { private static final String INNER_CLASS_EXAMPLE = "class Test {" + "interface A { String b();}" + "Integer i;}"; private static final String REFLECTION_EXAMPLE = "class Test { " + " String[] a = {\"java.util.Date\", \"hello\", \"www.w3c.org\"};" + " Class c = Integer.class;" + "}"; private static final Main JAVAC = new Main(); private static final String TMP = "temporaryDirectory" + File.separator; private static final String CLASS_NAME = "Test"; private static final String JAVA_FILE = TMP + CLASS_NAME + ".java"; private static final String CLASS_FILE = TMP + CLASS_NAME + ".class"; private static int compile(String file) { return JAVAC.compile(new String[] {file, "-target", "1.5"}); } private static AtomicVertex createVertex(String code, StringPattern reflectionPattern, boolean mergeInnerClasses) throws IOException { Writer writer = new FileWriter(JAVA_FILE); writer.write(code); writer.close(); assertEquals("Exit code", 0, compile(JAVA_FILE)); AtomicVertex[] vertices = Parser.readClassFiles(new String[] {TMP}, new TrueStringPattern(), reflectionPattern, mergeInnerClasses); for (int i = 0; i < vertices.length; i++) { NameAttributes attributes = (NameAttributes) vertices[i].getAttributes(); if (attributes.getName().equals(CLASS_NAME)) { AtomicVertex vertex = vertices[i]; return vertex; } } throw new IOException("Test class not found: " + Arrays.asList(vertices)); } public ParserTest(String name) { super(name); } protected void setUp() throws Exception { new File(TMP).mkdir(); } protected void tearDown() throws Exception { File dir = new File(TMP); File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { files[i].delete(); } dir.delete(); } private void check(String[] expectedClasses, String javaCode) throws IOException { check(expectedClasses, javaCode, null, false); } private void check(String[] expectedClasses, String javaCode, StringPattern reflectionPattern, boolean mergeInnerClasses) throws IOException { AtomicVertex vertex = createVertex(javaCode, reflectionPattern, mergeInnerClasses); assertEquals(TMP, ((ClassAttributes) vertex.getAttributes()).getSources()); HashSet classSet = new HashSet(); for (int i = 0; i < expectedClasses.length; i++) { classSet.add(expectedClasses[i]); } for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) { Vertex v = vertex.getHeadVertex(i); String name = ((ClassAttributes) v.getAttributes()).getName(); assertTrue(name + " not expected", classSet.contains(name)); classSet.remove(name); } assertEquals("number of classes (missing: " + classSet + ")", expectedClasses.length, vertex.getNumberOfOutgoingArcs()); } public void testParseFieldDescriptor() throws IOException { check(new String[] {"java.lang.Object", "java.awt.color.ICC_ColorSpace", "java.lang.String", "java.awt.LayoutManager2", "java.lang.StringBuffer"}, "class Test { String[][] a; java.awt.LayoutManager2 b; int i;" + "StringBuffer[] sb;" + "double[] d; boolean[][] z; java.awt.color.ICC_ColorSpace cs;}"); } public void testNoReflection() throws IOException { check(new String[] {"java.lang.Object", "java.lang.String", "java.lang.Class", "java.lang.Integer"}, REFLECTION_EXAMPLE); } public void testReflection() throws IOException { check(new String[] {"java.lang.Object", "java.lang.String", "java.lang.Class", "java.lang.Integer", "java.util.Date", "hello", "www.w3c.org"}, REFLECTION_EXAMPLE, new TrueStringPattern(), false); check(new String[] {"java.lang.Object", "java.lang.String", "java.lang.Class", "java.lang.Integer", "java.util.Date"}, REFLECTION_EXAMPLE, new WildCardPattern("java.*"), false); } public void testInvalidFieldDescriptors() throws IOException { check(new String[] {"java.lang.Object", "java.lang.String"}, "class Test { String[] a = {\"La;a\", \"[Lb;?\", \"L;\", \"L ;\"," + "\"La.;\", \"L.a;\", \"La..b;\", \"L1;\", };}"); } public void testParseMethodDescriptor() throws IOException { check(new String[] {"java.lang.String", "java.lang.Integer", "java.lang.Double", "java.lang.Boolean", "java.lang.Byte", "java.lang.Object", "java.lang.Long", "java.lang.Short", "java.lang.Exception", "java.lang.Class"}, "interface Test { void a(String a); int b(); Integer c();" + "Exception d(double d, Double d2); int e(Boolean[][] z);" + "short f(Byte b, int[][] i); Short g(Long l, Class c);}"); } public void testInvalidMethodDescriptors() throws IOException { check(new String[] {"java.lang.Object", "java.lang.String"}, "class Test { String[] a = {\"(La;\", \"(La1;??\", \"(Lb;)\"," + "\"(Lc;)?\", \"(Ld;)v\", \"(Le;)V?\", \"(Lf;)D?\", \"(Lg;)L1;\"," + "\"(Lh;)Li;?\", \"([)Lj;\", \"(L2;)Lk;\", \"( )Ll;\", \"(d)Lm;\"," + "\"(Ln;[)Lo;\", \"(Lp;L)V\"};}"); } public void testIndirectReference() throws IOException { check(new String[] {"java.lang.Object", "java.util.Enumeration", "java.lang.System", "java.util.Properties"}, "class Test { Object e = System.getProperties().keys();}"); } public void testConstantsReference() throws IOException { check(new String[] {"java.lang.Object"}, "class Test { int e = java.awt.Label.LEFT;}"); } public void testSuperClass() throws IOException { check(new String[] {"java.lang.Runnable", "java.awt.Canvas"}, "class Test extends java.awt.Canvas implements Runnable {" + "public void run() {}}"); } public void testCastingElementaryDataTypeArray() throws IOException { check(new String[] {"java.lang.Object"}, "class Test { Object a() { return null; } " + "void b() { byte[][] n = (byte[][]) a();}}"); } public void testInnerClasses() throws IOException { check(new String[] {"java.lang.Object", "java.lang.Integer", "Test$A"}, INNER_CLASS_EXAMPLE); } public void testMergeInnerClasses() throws IOException { check(new String[] {"java.lang.Object", "java.lang.Integer", "java.lang.String"}, INNER_CLASS_EXAMPLE, new TrueStringPattern(), true); // check that size of merged vertices is the sum of vertices sizes AtomicVertex vertex = createVertex(INNER_CLASS_EXAMPLE, new TrueStringPattern(), false); int size1 = ((ClassAttributes) vertex.getAttributes()).getSize(); Vertex innerClass = null; for (int i = 0; i < vertex.getNumberOfOutgoingArcs(); i++) { innerClass = vertex.getHeadVertex(i); String name = ((ClassAttributes) innerClass.getAttributes()).getName(); if (name.startsWith(CLASS_NAME)) { break; } } int size2 = ((ClassAttributes) innerClass.getAttributes()).getSize(); vertex = createVertex(INNER_CLASS_EXAMPLE, new TrueStringPattern(), true); int size = ((ClassAttributes) vertex.getAttributes()).getSize(); assertEquals(size1 + size2, size); } } ���������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ant/����������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0017522�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ant/ClassycleTaskTestCase.java��������������������������������������0000664�0000000�0000000�00000004557�12021221155�0024601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 01.07.2004 */ package classycle.ant; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import org.apache.tools.ant.BuildFileTest; /** * @author Franz-Josef Elmer */ public abstract class ClassycleTaskTestCase extends BuildFileTest { protected static final String TMP_DIR = "temporaryTestDirectory"; public ClassycleTaskTestCase(String arg0) { super(arg0); } protected void createTempDir() { new File(TMP_DIR).mkdir(); } protected void tearDown() throws Exception { File dir = new File(TMP_DIR); String[] files = dir.list(); for (int i = 0; i < files.length; i++) { File file = new File(TMP_DIR, files[i]); assertTrue("Couldn't delete " + file, file.delete()); } dir.delete(); } protected void checkNumberOfLines(int expectedNumberOfLines, String fileName) throws Exception { File file = new File(TMP_DIR, fileName); FileReader reader = new FileReader(file); checkNumberOfLines(reader, expectedNumberOfLines); } protected void checkNumberOfLines(Reader reader, int expectedNumberOfLines) throws IOException { BufferedReader br = new BufferedReader(reader); int numberOfLines = 0; while (br.readLine() != null) { numberOfLines++; } assertEquals("Number of lines", expectedNumberOfLines, numberOfLines); } protected void checkLine(String expectedLine, int lineNumber, String fileName) throws Exception { File file = new File(TMP_DIR, fileName); FileReader reader = new FileReader(file); checkLine(reader, expectedLine, lineNumber); } protected void checkLine(Reader reader, String expectedLine, int lineNumber) throws IOException { BufferedReader br = new BufferedReader(reader); String line = null; while ((line = br.readLine()) != null && --lineNumber > 0); assertEquals(expectedLine, line); } protected String readFile(String fileName) throws Exception { File file = new File(TMP_DIR, fileName); BufferedReader reader = new BufferedReader(new FileReader(file)); StringBuilder builder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { builder.append(line).append('\n'); } return builder.toString(); } } �������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ant/DependencyCheckingTaskTest.java���������������������������������0000664�0000000�0000000�00000012613�12021221155�0025565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 23.11.2004 */ package classycle.ant; import java.io.FileWriter; import java.io.IOException; import java.io.StringReader; import java.io.Writer; import org.apache.tools.ant.BuildException; /** * @author Franz-Josef Elmer */ public class DependencyCheckingTaskTest extends ClassycleTaskTestCase { public DependencyCheckingTaskTest(String arg0) { super(arg0); } protected void setUp() throws Exception { createTempDir(); configureProject("dependencyCheckingTaskTestBuild.xml"); } private void checkNumberOfOutputLines(int number) throws IOException { checkNumberOfLines(new StringReader(getOutput()), number); } private void checkLine(String expectedLine, int lineNumber) throws IOException { checkLine(new StringReader(getOutput()), expectedLine, lineNumber); } public void testEmbeddedDefinitions() throws Exception { executeTarget("testEmbeddedDefinitions"); checkNumberOfOutputLines(14); checkLine(" <unexpected-dependencies statement='check [A] independentOf [non-A]'/>", 3); checkLine(" <unexpected-dependencies statement='check [non-A] independentOf [A]'>", 4); } public void testEmbeddedDefinitionsFailureOn() throws Exception { try { executeTarget("testEmbeddedDefinitionsFailureOn"); fail("BuildException expected"); } catch (BuildException e) { checkNumberOfOutputLines(10); checkLine("check [A] independentOf [non-A]\tOK", 2); checkLine("check [non-A] independentOf [A]", 3); checkLine(" Unexpected dependencies found:", 4); } } public void testCheckCyclesMergedInnerClassesFailureOn() throws Exception { executeTarget("testCheckCyclesMergedInnerClassesFailureOn"); assertEquals("<?xml version='1.0' encoding='UTF-8'?>\n" + "<dependency-checking-results>\n" + " <cycles statement='check absenceOfClassCycles > 1 " + "in example.*' vertex-type='class'/>\n" + "</dependency-checking-results>\n", readFile("dependency-checking-result.xml")); } public void testCheckCyclesFailureOn() throws Exception { try { executeTarget("testCheckCyclesFailureOn"); fail("BuildException expected"); } catch (BuildException e) { checkNumberOfOutputLines(4); checkLine("check absenceOfClassCycles > 1 in example.*", 1); checkLine(" example.B and inner classes contains 2 classes:", 2); checkLine(" example.B", 3); checkLine(" example.B$M", 4); } } public void testExcluding() throws Exception { executeTarget("testExcluding"); checkNumberOfOutputLines(8); } public void testResetGraphAfterCheck() throws Exception { executeTarget("testResetGraphAfterCheck"); checkNumberOfOutputLines(8); checkLine("check [A-not-p] independentOf *h*", 1); checkLine("check [A-not-p] independentOf *S*", 5); checkLine(" -> java.lang.String", 8); } public void testDependentOnlyOn() throws Exception { executeTarget("testDependentOnlyOn"); assertEquals("check example.B* dependentOnlyOn java.lang.* example.A*\n" + " Unexpected dependencies found:\n" + " example.B$M\n" + " -> example.p.A\n" + " example.BofA\n" + " -> example.p.A\n" + "check [set] dependentOnlyOn java.lang.*\n" + " Unexpected dependencies found:\n" + " example.B$M\n" + " -> example.A\n" + " example.p.A\n" + " -> example.A\n" + " example.B\n" + " -> example.A\n" + "check example.B* dependentOnlyOn *A\n" + " Unexpected dependencies found:\n" + " example.B$M\n" + " -> java.lang.Object\n" + " example.BofA\n" + " -> java.lang.Object\n" + " -> java.lang.Class\n" + " -> java.lang.Thread\n", getOutput()); } public void testReflection() throws Exception { executeTarget("testReflection"); checkNumberOfOutputLines(6); checkLine("check [A-not-p] independentOf *h*", 1); assertTrue(getOutput().indexOf("-> hello") > 0); } public void testReflectionWithRestriction() throws Exception { executeTarget("testReflectionWithRestriction"); checkNumberOfOutputLines(4); checkLine("check [A-not-p] independentOf *h*", 1); assertTrue(getOutput().indexOf("-> java.lang.Thread") > 0); } public void testFile() throws Exception { Writer writer = new FileWriter(TMP_DIR + "/test.ddf"); writer.write("show allResults\n" + "[A] = *A*\n" + "[non-A] = example.* excluding [A]\n" + "check [A] independentOf [non-A]"); writer.close(); executeTarget("testFile"); checkNumberOfOutputLines(2); checkLine("check [A] independentOf [non-A]\tOK", 2); } public void testNoClasses() throws Exception { try { executeTarget("testNoClasses"); fail("BuildException expected"); } catch (BuildException e) { checkNumberOfOutputLines(0); } } public void testEmpty() throws Exception { try { executeTarget("testEmpty"); fail("BuildException expected"); } catch (BuildException e) { checkNumberOfOutputLines(0); assertEquals("Empty dependency definition.", e.getMessage()); } } } ���������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/ant/ReportTaskTest.java���������������������������������������������0000664�0000000�0000000�00000005750�12021221155�0023332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 01.07.2004 */ package classycle.ant; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.tools.ant.BuildException; /** * @author Franz-Josef Elmer */ public class ReportTaskTest extends ClassycleTaskTestCase { public ReportTaskTest(String arg0) { super(arg0); } protected void setUp() throws Exception { createTempDir(); configureProject("reportTaskTestBuild.xml"); } public void testRaw() throws Exception { executeTarget("testRaw"); checkNumberOfLines(23, "reportTaskTest.txt"); } public void testMergeInnerClasses() throws Exception { executeTarget("testMergeInnerClasses"); checkNumberOfLines(19, "reportTaskTest.txt"); } public void testOnlyA() throws Exception { executeTarget("testOnlyA"); checkNumberOfLines(14, "reportTaskTest.txt"); } public void testIncludingA() throws Exception { executeTarget("testIncludingA"); checkNumberOfLines(14, "reportTaskTest.txt"); } public void testIncludingAExcludingB() throws Exception { executeTarget("testIncludingAExcludingB"); checkNumberOfLines(9, "reportTaskTest.txt"); } public void testIncludingAExcludingBp() throws Exception { executeTarget("testIncludingAExcludingBp"); checkNumberOfLines(6, "reportTaskTest.txt"); } public void testCSV() throws Exception { executeTarget("testCSV"); checkNumberOfLines(7, "reportTaskTest.csv"); } public void testXML() throws Exception { executeTarget("testXML"); checkNumberOfLines(90, "reportTaskTest.xml"); } public void testReflectionAll() throws Exception { executeTarget("testReflectionAll"); checkNumberOfLines(24, "reportTaskTest.txt"); } public void testReflectionRestricted() throws Exception { executeTarget("testReflectionRestricted"); checkNumberOfLines(23, "reportTaskTest.txt"); } public void testXMLPackagesOnly() throws Exception { executeTarget("testXMLPackagesOnly"); checkNumberOfLines(34, "reportTaskTest.xml"); String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); checkLine("<classycle title='<hel&lo>' date='" + date + "'>", 3, "reportTaskTest.xml"); } public void testInvalidReportType() throws Exception { try { executeTarget("testInvalidReportType"); fail("BuildException expected"); } catch (BuildException e) { assertTrue(e.getMessage().indexOf("foo") >= 0); } } public void testMissingReportFile() throws Exception { try { executeTarget("testMissingReportFile"); fail("BuildException expected"); } catch (BuildException e) { assertTrue(e.getMessage().indexOf("'reportFile'") >= 0); } } public void testMissingFileSet() throws Exception { try { executeTarget("testMissingFileSet"); fail("BuildException expected"); } catch (BuildException e) { assertTrue(e.getMessage().indexOf("file set") >= 0); } } } ������������������������classycle-1.4/srcTest/classycle/dependency/���������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0021056�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/dependency/DependencyDefinitionParserTest.java����������������������0000664�0000000�0000000�00000025273�12021221155�0030036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 30.08.2004 */ package classycle.dependency; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import junit.framework.TestCase; import classycle.util.StringPattern; /** * @author Franz-Josef Elmer */ public class DependencyDefinitionParserTest extends TestCase { private Hashtable _defaultProps; public void testShowStatements() { check("show a b c", new String[] {"[a, b, c]"}); check("show a\n show b c", new String[] {"[a]", "[b, c]"}); } public void testCheckSetStatements() { check("check sets ${package}.lang.*", new String[] {"check set java.lang.*"}); check("[lang] = java.lang.*\n" + "check sets [lang] java.util.*", new String[] {"check set [lang]", "check set java.util.*"}); } public void testCheckCycleStatements() { check("[base] = base.*\n" + "check absenceOfClassCycles > 10 in java.lang.*\n" + "check absenceOfPackageCycles > 1 in [base]", new String[] {"check absenceOfClassCycles > 10 in java.lang.*", "check absenceOfPackageCycles > 1 in [base]"}); } public void testCheckMissSpelledKeywords() { try { createParser("[set] = b.* exluding *Test"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("exluding", e); } try { createParser("check b.* independentof [set]"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("independentof", e); } try { createParser("check b.* dependingOn [set]"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("dependingOn", e); } try { createParser("check layeringof [set]"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("layeringof", e); } try { createParser("layer l = layer"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("layer", e); } try { createParser("check sets set1"); fail("IllegalArgumentException expected because of miss-spelled keyword"); } catch (IllegalArgumentException e) { assertContains("set1", e); } } private void assertContains(String expectedMessageFragment, Throwable throwable) { String message = throwable.getMessage(); assertTrue("<" + message + "> does not contain <" + message + ">", message.indexOf(expectedMessageFragment) >= 0); } public void testDependencyStatements() { check("check java.lang.Integer dependentOnlyOn java.lang.Number", new String[] {"check java.lang.Integer dependentOnlyOn java.lang.Number"}); check("check java.lang.* independentOf ${awt}", new String[] {"check java.lang.* independentOf java.awt.*"}); check("[lang] = java.lang.*\n" + "show shortestPathsOnly\n" + "check [lang] independentOf java.awt.*", new String[] {"[shortestPathsOnly]", "check [lang] independentOf java.awt.*"}); check("[lang] = java.lang.*\n" + " check [lang] ${package}.util.* independentOf ${awt}", new String[] {"check [lang] java.util.* independentOf java.awt.*"}); check("{jojo} = ${package} \n" + "[lang] = java.lang.*\n" + " check [lang] ${jojo}.util.* independentOf\\\njava.awt.*", new String[] {"check [lang] java.util.* independentOf java.awt.*"}); assertEquals(2, _defaultProps.size()); // We expect ${jojo} not in there check("######\n" + "[lang] = java.lang.*\n" + "# this is a comment\n" + " # and this too\n\r\n" + "check [lang] java.util.* independentOf \\ \n java.awt.*\n" + "check java.util.* independentOf \\\n javax.swing.* java.awt.*\n", new String[] {"check [lang] java.util.* independentOf java.awt.*", "check java.util.* independentOf javax.swing.* java.awt.*"}); check("[lang] = java.lang.*\n" + "check [lang] java.util.* independentOf\\ \n# hello\njava.awt.*", new String[] {"check [lang] java.util.* independentOf java.awt.*"}); check("[lang] = java.lang.*\n" + "[a] = [lang] excluding java.lang.Class\n" + "check [a] independentOf java.awt.*", new String[] {"check [a] independentOf java.awt.*"}); } public void testLayeringStatements() { check("layer a = java.lang.*\n" + "layer b = java.util.*\n" + "check layeringOf a b", new String[] {"check layeringOf a b"}); check("layer a = java.lang.*\n" + "layer b = java.util.*\n" + "check strictLayeringOf a b", new String[] {"check strictLayeringOf a b"}); } public void testSetDefinition() { check("[a] = j.*", new String[][] {{"[a]", "j.*"}}); check("[a] = j.* k.*", new String[][] {{"[a]", "j.* k.*"}}); check("[a] = j.* k.* excluding a.b", new String[][] {{"[a]", "(j.* k.* & !a.b)"}}); check("[a] = j.* k.* excluding a.b c.d", new String[][] {{"[a]", "(j.* k.* & !(a.b c.d))"}}); check("[a] = k$t.*_$ excluding a.b c.d", new String[][] {{"[a]", "(k$t.*_$ & !(a.b c.d))"}}); check("[a] = excluding a.b c.d", new String[][] {{"[a]", "!(a.b c.d)"}}); } public void testSetDefinitions() { check("[a] = a.*\n" + "[b] = b.*\n" + "[c] = [a] excluding j.*", new String[][] {{"[a]", "a.*"}, {"[b]", "b.*"}, {"[c]", "(a.* & !j.*)"} }); check("[a] = a.*\n" + "[b] = b.*\n" + "[c] = [a] j.*\n" + "[d] = j.* [b] excluding [c] k.*\n", new String[][] {{"[a]", "a.*"}, {"[b]", "b.*"}, {"[c]", "a.* j.*"}, {"[d]", "(j.* b.* & !(a.* j.* k.*))"} }); } public void testLayerDefinitions() { check("[a] = a.*\n" + "[b] = b.*\n" + "[c] = [a] excluding j.*\n" + "layer a = z.*\n" + "layer b = [c]\n" + "layer bla = [a] [c]\n" + "layer c = [a] s.*\n", new String[] {"a", "b", "bla", "c"}, new String[][] {{"z.*"}, {"(a.* & !j.*)"}, {"a.*", "(a.* & !j.*)"}, {"a.*", "s.*"} }); } private void check(String definition, String[] expectedStatements) { DependencyDefinitionParser parser = createParser(definition); Statement[] statements = parser.getStatements(); int len = Math.min(statements.length, expectedStatements.length); for (int i = 0; i < len; i++) { assertEquals("Statement " + (i + 1), expectedStatements[i], statements[i].toString()); } if (len < statements.length) { fail(statements.length - len + " additional statements"); } if (len < expectedStatements.length) { fail(expectedStatements.length - len + " missing statements"); } } private DependencyDefinitionParser createParser(String definition) { _defaultProps = new Hashtable(); _defaultProps.put("package", "java"); _defaultProps.put("awt", "java.awt.*"); DependencyProperties properties = new DependencyProperties(_defaultProps); DependencyDefinitionParser parser = new DependencyDefinitionParser(definition, properties, new MockResultRenderer()); return parser; } private void check(String definition, String[][] expectedSets) { DependencyDefinitionParser parser = createParser(definition); SetDefinitionRepository definitions = parser._setDefinitions; for (int i = 0; i < expectedSets.length; i++) { String setName = expectedSets[i][0]; String expectedSet = expectedSets[i][1]; assertEquals("Set " + setName, expectedSet, definitions.getPattern(setName) + ""); } } private void check(String definition, String[] layerNames, String[][] expectedLayers) { DependencyDefinitionParser parser = createParser(definition); LayerDefinitionRepository definitions = parser._layerDefinitions; for (int i = 0; i < expectedLayers.length; i++) { StringPattern[] layer = definitions.getLayer(layerNames[i]); int n = Math.min(layer.length, expectedLayers[i].length); for (int j = 0; j < n; j++) { assertEquals("Layer " + layerNames[i] + " " + j, expectedLayers[i][j], layer[j] + ""); } int d = expectedLayers[i].length - layer.length; if (d > 0) { fail(d + " terms missed"); } else if (d < 0) { fail(-d + " unexpected terms"); } } } private static class MockPreference implements Preference { String _preference; public MockPreference(String preference) { _preference = preference; } public String getKey() { return _preference; } public String toString() { return _preference; } } private static class MockPreferenceFactory implements PreferenceFactory { private final HashMap _keyToPreferenceMap = new HashMap(); public Preference get(String key) { Preference preference = (Preference) _keyToPreferenceMap.get(key); if (preference == null) { preference = new MockPreference(key); _keyToPreferenceMap.put(key, preference); } return preference; } } private static class MockResultRenderer extends ResultRenderer { ArrayList list = new ArrayList(); private PreferenceFactory _factory = new MockPreferenceFactory(); public void considerPreference(Preference preference) { list.add(preference); } public Result getDescriptionOfCurrentPreferences() { return new MockResult(list.toString()); } public PreferenceFactory getPreferenceFactory() { return _factory; } public String render(Result result) { return null; } } private static class MockResult implements Result { String value; public MockResult(String value) { this.value = value; } public boolean isOk() { return true; } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/dependency/DependencyProcessorTest.java�����������������������������0000664�0000000�0000000�00000020623�12021221155�0026542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 04.09.2004 */ package classycle.dependency; import junit.framework.TestCase; import classycle.graph.AtomicVertex; import classycle.graph.GraphTestCase.MockAttributes; /** * @author Franz-Josef Elmer */ public class DependencyProcessorTest extends TestCase { private static final String DIDOF = ' ' + DependencyDefinitionParser.DIRECTLY_INDEPENDENT_OF_KEY_WORD + ' '; private static final String CHECK = DependencyDefinitionParser.CHECK_KEY_WORD + ' '; private static final String OK = DependencyResult.OK + '\n'; private String DF = DependencyResult.DEPENDENCIES_FOUND; private static final String SHOW_ALLRESULTS = "show allResults\n"; private static final String SHOW_ALL = "show allPaths allResults\n"; private static final String SHOW_ONLY_ALL = "show onlyShortestPaths allResults\n"; public DependencyProcessorTest(String s) { super(s); } public void testCheckSets() { String s = "[a] = a.*\n" + "check sets [a] b.* bla.bla"; check(SHOW_ALLRESULTS + s, new String[] {SHOW_ONLY_ALL, "Set [a] has 2 classes.\n", "Set b.* has one class.\n", "Set bla.bla is empty.\n"}); check(s, new String[] {"", "", "Set bla.bla is empty.\n"}); } public void testClassCycleCheck() { String s = "[a] = a.*\n" + "check absenceOfClassCycles > 1 in b.*\n" + "check absenceOfClassCycles > 1 in [a]"; String result = "check absenceOfClassCycles > 1 in [a]\n" + " a.A et al. contains 2 classes:\n" + " a.A\n" + " a.B\n"; check(SHOW_ALLRESULTS + s, new String[] {SHOW_ONLY_ALL, "check absenceOfClassCycles > 1 in b.*\tOK\n", result}); check(s, new String[] {"", result}); } public void testPackageCycleCheck() { String s = "[A] = *.A\n" + "check absenceOfPackageCycles > 1 in *.B\n" + "check absenceOfPackageCycles > 1 in [A]"; String result = "check absenceOfPackageCycles > 1 in [A]\n" + " i et al. contains 2 packages:\n" + " i\n" + " b\n"; check(SHOW_ALLRESULTS + s, new String[] {SHOW_ONLY_ALL, "check absenceOfPackageCycles > 1 in *.B\tOK\n", result}); check(s, new String[] {"", result}); } public void testSimpleDependencyCheck() { String s = "check b.* independentOf c.*"; check(SHOW_ALLRESULTS + s + "\nshow allPaths", new String[] {SHOW_ONLY_ALL, s + OK, SHOW_ALL}); s = "check f.* independentOf b.*"; check(SHOW_ALLRESULTS + s, new String[] {SHOW_ONLY_ALL, s + DF + "\n f.A\n -> b.A\n"}); } public void testPreferences() { String s1 = "check b.* independentOf c.*"; String s2 = "check f.* independentOf b.*"; String s = s1 + '\n' + s2 + '\n'; check(s + SHOW_ALLRESULTS + s + "show onlyFailures\n" + s, new String[] {"", s2 + DF + "\n f.A\n -> b.A\n", SHOW_ONLY_ALL, s1 + OK, s2 + DF + "\n f.A\n -> b.A\n", "", "", s2 + DF + "\n f.A\n -> b.A\n"}); } public void testSwitchAllPathsAndBack() { String s = "check h.* independentOf b.*"; check(SHOW_ALLRESULTS + s + "\nshow allPaths\n" + s + "\nshow onlyShortestPaths\n" + s, new String[] {SHOW_ONLY_ALL, s + DF + "\n h.A\n -> f.A\n -> b.A\n", SHOW_ALL, s + DF + "\n h.A\n -> e.A\n -> e.B\n" + " -> b.A\n -> f.A\n -> b.A\n", SHOW_ONLY_ALL, s + DF + "\n h.A\n -> f.A\n -> b.A\n"}); } public void testLayering() { check(SHOW_ALLRESULTS + "layer bc = b.* c.*\n" + "layer f = f.*\n" + "check layeringOf bc f", new String[] {SHOW_ONLY_ALL, CHECK + "b.*" + DIDOF + "c.*" + OK + CHECK + "c.*" + DIDOF + "b.*" + OK + CHECK + "b.*" + DIDOF + "f.*" + OK + CHECK + "c.*" +DIDOF + "f.*" + OK}); String result = CHECK + "[a]" + DIDOF + "b.*" + OK + CHECK + "[a]" + DIDOF + "c.*" + OK + CHECK + "b.*" + DIDOF + "[a]" + OK + CHECK + "b.*" + DIDOF + "c.*" + OK + CHECK + "c.*" + DIDOF + "[a]" + OK + CHECK + "c.*" + DIDOF + "b.*" + OK + CHECK + "[a]" + DIDOF + "e.*" + OK + CHECK + "[a]" + DIDOF + "f.*" + OK + CHECK + "b.*" + DIDOF + "e.*" + OK + CHECK + "b.*" + DIDOF + "f.*" + OK + CHECK + "c.*" + DIDOF + "e.*" + OK + CHECK + "c.*" + DIDOF + "f.*" + OK + CHECK + "[a]" + DIDOF + "h.*" + OK + CHECK + "b.*" + DIDOF + "h.*" + OK + CHECK + "c.*" + DIDOF + "h.*" + OK + CHECK + "e.*" + DIDOF + "f.*" + OK + CHECK + "f.*" + DIDOF + "e.*" + OK + CHECK + "e.*" + DIDOF + "h.*" + OK + CHECK + "f.*" + DIDOF + "h.*" + OK; check(SHOW_ALLRESULTS + "[a] = a.* excluding a.B\n" + "layer abc = [a] b.* c.* \n" + "layer ef = e.* f.*\n" + "layer h = h.*\n" + "check layeringOf abc ef h\n" + "check strictLayeringOf abc ef h", new String[] {SHOW_ONLY_ALL, result, result + CHECK + "h.*" +DIDOF + "[a]" + DF + "\n h.A\n -> a.A\n" + CHECK + "h.*" +DIDOF + "b.*" + OK + CHECK + "h.*" +DIDOF + "c.*" + OK }); check("[a] = a.* excluding a.B\n" + "layer abc = [a] b.* c.* \n" + "layer ef = e.* f.*\n" + "layer h = h.*\n" + "check layeringOf abc ef h\n" + "check strictLayeringOf abc ef h", new String[] {"", CHECK + "h.*" +DIDOF + "[a]" + DF + "\n h.A\n -> a.A\n"}); } private void check(String description, String[] expectedResults) { AtomicVertex[] graph = createGraph(); ResultRenderer renderer = new DefaultResultRenderer(); DependencyProcessor processor = new DependencyProcessor(description, null, renderer); int i = 0; while (processor.hasMoreStatements()) { assertEquals("Result " + i, expectedResults[i++], renderer.render(processor.executeNextStatement(graph))); } if (i < expectedResults.length) { fail((expectedResults.length - i) + " more results expected"); } } private AtomicVertex[] createGraph() { return createGraph(new String[] {"a.A", "a.B", "b.A", "c.A", "e.A", "e.B", "f.A", "h.A", "i.A", }, new int[][] {{1}, // 0: a.A {0}, // 1: a.B {8}, // 2: b.A {}, // 3: c.A {0, 5}, // 4: e.A {2}, // 5: e.B {2}, // 6: f.A {0, 4, 6},// 7: h.A {2}, // 8: i.A }); } private AtomicVertex[] createGraph(String[] nodes, int[][] nodeLinks) { AtomicVertex[] result = new AtomicVertex[nodes.length]; for (int i = 0; i < result.length; i++) { result[i] = new AtomicVertex(new MockAttributes(nodes[i])); } for (int i = 0; i < result.length; i++) { int[] links = nodeLinks[i]; for (int j = 0; j < links.length; j++) { int link = links[j]; result[i].addOutgoingArcTo(result[link]); } } return result; } } �������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/dependency/XMLResultRendererTest.java�������������������������������0000664�0000000�0000000�00000011040�12021221155�0026103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2011 Franz-Josef Elmer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package classycle.dependency; import java.util.Arrays; import junit.framework.TestCase; import classycle.PackageAttributes; import classycle.graph.AtomicVertex; import classycle.graph.StrongComponent; import classycle.util.WildCardPattern; public class XMLResultRendererTest extends TestCase { public void testCyclesResultOk() { CyclesResult result = new CyclesResult("test statement", false); assertEquals("<?xml version='1.0' encoding='UTF-8'?>\n" + "<dependency-checking-results>\n" + " <cycles statement='test statement' vertex-type='class'/>\n" + "</dependency-checking-results>\n", new XMLResultRenderer().render(result)); } public void testCyclesResultWithCycles() { CyclesResult result = new CyclesResult("test statement", true); StrongComponent c1 = new StrongComponent(); c1.addVertex(new AtomicVertex(new PackageAttributes("p1"))); c1.addVertex(new AtomicVertex(new PackageAttributes("p2"))); c1.calculateAttributes(); result.addCycle(c1); StrongComponent c2 = new StrongComponent(); c2.addVertex(new AtomicVertex(new PackageAttributes("p3"))); c2.calculateAttributes(); result.addCycle(c2); assertEquals("<?xml version='1.0' encoding='UTF-8'?>\n" + "<dependency-checking-results>\n" + " <cycles statement='test statement' vertex-type='package'>\n" + " <cycle name='p2 et al.'>\n" + " <class>p2</class>\n" + " <class>p1</class>\n" + " </cycle>\n" + " <cycle name='p3'>\n" + " <class>p3</class>\n" + " </cycle>\n" + " </cycles>\n" + "</dependency-checking-results>\n", new XMLResultRenderer().render(result)); } public void testDependencyResult() { AtomicVertex a = new AtomicVertex(new PackageAttributes("a")); AtomicVertex b = new AtomicVertex(new PackageAttributes("b")); AtomicVertex c1 = new AtomicVertex(new PackageAttributes("c1")); AtomicVertex c2 = new AtomicVertex(new PackageAttributes("c2")); AtomicVertex c3 = new AtomicVertex(new PackageAttributes("c3")); AtomicVertex d = new AtomicVertex(new PackageAttributes("d")); a.addOutgoingArcTo(b); b.addOutgoingArcTo(c1); b.addOutgoingArcTo(c2); a.addOutgoingArcTo(c3); d.addOutgoingArcTo(a); c1.addOutgoingArcTo(a); AtomicVertex[] vertices = Arrays.asList(a, b, c1, c2, c3, d).toArray(new AtomicVertex[0]); WildCardPattern startSet = new WildCardPattern("a*"); WildCardPattern finalSet = new WildCardPattern("c*"); DependencyResult result = new DependencyResult(startSet, finalSet, "the statement", vertices); assertEquals("<?xml version='1.0' encoding='UTF-8'?>\n" + "<dependency-checking-results>\n" + " <unexpected-dependencies statement='the statement'>\n" + " <node name='a'>\n" + " <node name='b'>\n" + " <node name='c1'/>\n" + " <node name='c2'/>\n" + " </node>\n" + " <node name='c3'/>\n" + " </node>\n" + " </unexpected-dependencies>\n" + "</dependency-checking-results>\n", new XMLResultRenderer().render(result)); } public void testResultContainerAndTextResult() { ResultContainer c1 = new ResultContainer(); c1.add(new TextResult("hello world")); ResultContainer c2 = new ResultContainer(); c2.add(new TextResult("Invalid set", false)); c2.add(new TextResult("Unknown", false)); c2.add(new TextResult("")); c1.add(c2); assertEquals("<?xml version=\'1.0' encoding='UTF-8'?>\n" + "<dependency-checking-results>\n" + " <info>hello world</info>\n" + " <checking-error>Invalid set</checking-error>\n" + " <checking-error>Unknown</checking-error>\n" + "</dependency-checking-results>\n", new XMLResultRenderer().render(c1)); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/��������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0020041�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/AtomicVertexTest.java�����������������������������������������0000664�0000000�0000000�00000002245�12021221155�0024161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle.graph; import junit.framework.TestCase; public class AtomicVertexTest extends TestCase { public AtomicVertexTest(String name) { super(name); } public void testGraphVertexProperty() { AtomicVertex vertex = new AtomicVertex(null); assertTrue(!vertex.isGraphVertex()); vertex.reset(); assertTrue(vertex.isGraphVertex()); vertex.reset(); assertTrue(vertex.isGraphVertex()); } public void testOrderProperty() { AtomicVertex vertex = new AtomicVertex(null); assertEquals(0, vertex.getOrder()); vertex.reset(); assertEquals(-1, vertex.getOrder()); vertex.reset(); assertEquals(-1, vertex.getOrder()); vertex.setOrder(42); assertEquals(42, vertex.getOrder()); vertex.reset(); assertEquals(-1, vertex.getOrder()); } public void testLowProperty() { AtomicVertex vertex = new AtomicVertex(null); assertEquals(0, vertex.getLow()); vertex.reset(); assertEquals(-1, vertex.getLow()); vertex.reset(); assertEquals(-1, vertex.getLow()); vertex.setLow(42); assertEquals(42, vertex.getLow()); vertex.reset(); assertEquals(-1, vertex.getLow()); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/GraphTestCase.java��������������������������������������������0000664�0000000�0000000�00000005420�12021221155�0023402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle.graph; import java.util.Arrays; import java.util.HashSet; import classycle.ClassAttributes; import junit.framework.TestCase; public abstract class GraphTestCase extends TestCase { public static class MockAttributes extends ClassAttributes { public MockAttributes(String name) { super(name, "", ClassAttributes.CLASS, 42); } public int getSize() { return 0; } public String toString() { return getName(); } } protected AtomicVertex _externalVertex = new AtomicVertex(null); public GraphTestCase(String s) { super(s); } protected StrongComponent[] check(String[] expectedStrongComponents, int[][] nodeLinks) { HashSet expectedFingerPrints = new HashSet(); for (int i = 0; i < expectedStrongComponents.length; i++) { expectedFingerPrints.add(expectedStrongComponents[i]); } AtomicVertex[] graph = createGraph(nodeLinks); StrongComponentProcessor processor = new StrongComponentProcessor(true); process(processor, graph); StrongComponent[] components = processor.getStrongComponents(); for (int i = 0; i < components.length; i++) { String fingerPrint = createFingerPrint(components[i]); assertTrue("'" + fingerPrint + "' not expected", expectedFingerPrints.contains(fingerPrint)); } assertEquals("number of strong components", expectedStrongComponents.length, components.length); return components; } protected void process(StrongComponentProcessor processor, AtomicVertex[] graph) { processor.deepSearchFirst(graph); } private String createFingerPrint(StrongComponent component) { int[] vertices = new int[component.getNumberOfVertices()]; for (int i = 0; i < vertices.length; i++) { vertices[i] = Integer.parseInt(((MockAttributes) component.getVertex(i) .getAttributes()).toString()); } Arrays.sort(vertices); StringBuffer result = new StringBuffer(); result.append(component.getLongestWalk()).append(':'); for (int i = 0; i < vertices.length; i++) { result.append(' ').append(Integer.toString(vertices[i])); } return new String(result); } protected AtomicVertex[] createGraph(int[][] nodeLinks) { AtomicVertex[] result = new AtomicVertex[nodeLinks.length]; for (int i = 0; i < result.length; i++) { result[i] = new AtomicVertex(new MockAttributes(Integer.toString(i))); } for (int i = 0; i < result.length; i++) { int[] links = nodeLinks[i]; for (int j = 0; j < links.length; j++) { int link = links[j]; result[i].addOutgoingArcTo(link < 0 ? _externalVertex : result[link]); } } return result; } } //class������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/LongestWalkProcessorTest.java���������������������������������0000664�0000000�0000000�00000007143�12021221155�0025703�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle.graph; /** * * * @author Franz-Josef Elmer */ public class LongestWalkProcessorTest extends GraphTestCase { public LongestWalkProcessorTest(String s) { super(s); } protected void process(StrongComponentProcessor processor, AtomicVertex[] graph) { processor.deepSearchFirst(graph); new LongestWalkProcessor().deepSearchFirst( processor.getStrongComponents()); } public void testOneVertexGraphs() { check(new String[] {"0: 0"}, new int[][] {{}}); } public void testTwoVerticesGraphs() { check(new String[] {"0: 0 1"}, new int[][] {{1},{0}}); check(new String[] {"0: 0", "0: 1"}, new int[][] {{},{}}); check(new String[] {"0: 1", "0: 0"}, new int[][] {{0},{1,-1}}); check(new String[] {"1: 1", "0: 0"}, new int[][] {{0},{0}}); } public void testThreeVerticesGraphs() { check(new String[] {"0: 0", "0: 1", "0: 2"}, new int[][] {{},{},{-1}}); check(new String[] {"0: 0", "2: 1", "1: 2"}, new int[][] {{0},{2},{0}}); check(new String[] {"0: 0 1", "0: 2"}, new int[][] {{1},{0},{-1,2}}); check(new String[] {"0: 0 1", "1: 2"}, new int[][] {{1},{0,1},{0}}); check(new String[] {"1: 0 1", "0: 2"}, new int[][] {{1,2},{0,1},{}}); check(new String[] {"1: 2", "0: 0 1"}, new int[][] {{1},{0},{0,1}}); check(new String[] {"0: 0 2", "1: 1"}, new int[][] {{-1,2},{0},{-1,0}}); check(new String[] {"0: 0 1 2"}, new int[][] {{2},{0},{1}}); } public void testComplexGraphs() { check(new String[] {"1: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {1, -1, 4}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"1: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {1, -1, 4}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"1: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {4, -1, 1}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"1: 0 1 2 3 6", "0: 4 5", "0: 7"}, new int[][] {{1}, // 0 {2}, // 1 {2, 3, -1, 4}, // 2 {1, -1, 0, 6}, // 3 {5}, // 4 {4}, // 5 {3, 7}, // 6 {-1} // 7 }); check(new String[] {"2: 0", "0: 1", "1: 2 6", "2: 4", "3: 3 7 8", "1: 5"}, new int[][] {{2}, // 0 {-1}, // 1 {1, 6, -1}, // 2 {7, -1, 4}, // 3 {6}, // 4 {1}, // 5 {2, -1}, // 6 {8, 5, -1}, // 7 {3, -1} // 8 }); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/PathsFinderTest.java������������������������������������������0000664�0000000�0000000�00000017561�12021221155�0023765�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 18.06.2004 */ package classycle.graph; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.StringTokenizer; import junit.framework.TestCase; /** * @author Franz-Josef Elmer */ public class PathsFinderTest extends TestCase { private static class MockVertexCondition implements VertexCondition { private final HashSet _vertices = new HashSet(); public MockVertexCondition(Vertex[] vertices) { for (int i = 0; i < vertices.length; i++) { _vertices.add(vertices[i]); } } public boolean isFulfilled(Vertex vertex) { return _vertices.contains(vertex); } } private static final HashMap REPOSITORY = new HashMap(); private static final HashSet GRAPH = new HashSet(); private static MockVertex getVertex(String name) { MockVertex vertex = (MockVertex) REPOSITORY.get(name); if (vertex == null) { vertex = new MockVertex(name); } if (!name.startsWith("$")) { GRAPH.add(vertex); } return vertex; } private static MockVertex[] getAllVertices() { return (MockVertex[]) GRAPH.toArray(new MockVertex[0]); } private static class MockVertex extends AtomicVertex { public int countReset; public int countVisit; public final String name; public MockVertex(String name) { super(null); this.name = name; REPOSITORY.put(name, this); } public void reset() { countReset++; super.reset(); } public void visit() { countVisit++; super.visit(); } public String toString() { return name; } } public PathsFinderTest(String name) { super(name); } public void testFindAllPaths() { check("a b c", "e f", "a d e", "a > b c d h, c > b k, d > e g", false); MockVertex a = getVertex("a"); MockVertex b = getVertex("b"); MockVertex c = getVertex("c"); assertEquals(0, a.getNumberOfIncomingArcs()); assertEquals(4, a.getNumberOfOutgoingArcs()); assertSame(b, a.getHeadVertex(0)); assertSame(c, a.getHeadVertex(1)); assertEquals(2, b.getNumberOfIncomingArcs()); assertEquals(0, b.getNumberOfOutgoingArcs()); assertSame(a, b.getTailVertex(0)); assertSame(c, b.getTailVertex(1)); check("a b c", "e f", "a d e f h i g", "a > b c d h," + "c > b k," + "h > d i," + "i > h f," + "e > f," + "f > e g," + "g > b e," + "d > e g", false); check("a b", "h $1 $2", "a b c d e g h $1 $2", "a > b c $2," + "c > a e," + "d > $1 k l," + "e > f g," + "g > f h," + "h > j," + "j > e," + "k > l," + "l > d," + "b > c d", false); check("a", "f", "a b c d e f", "a > b, b > c d, c > e, d > e, e > f", false); check("a", "c", "", "a > b, c > b", false); check("a", "b d e", "a b e", "a > b e, b > c d e", false); check("a f", "b d e", "a b e", "a > b e, b > c d e, f > a", false); check("a b", "e", "a c e", "a > c, c > e, b > d, d > a", false); check("a", "b", "a b c d", "a > b c, c > b d, d > b c", false); check("a", "e", "a b c d e f", "a > b, b > c f, c > d, d > e, f > e", false); } public void testFindShortestPaths() { check("a b c", "e f", "a d e", "a > b c d h, c > b k, d > e g", true); check("a b", "h i", "a b c d e g h i", "a > b c," + "c > a e," + "d > i k l," + "e > f g," + "g > f h," + "h > j," + "j > e," + "k > l," + "l > d," + "b > c d", true); check("a", "f", "a b c d e f", "a > b, b > c d, c > e, d > e, e > f", true); check("a", "c", "", "a > b, c > b", true); check("a", "e", "a b f e", "a > b, b > c f, c > d, d > e, f > e", true); check("a b", "e", "a b c d e", "a > c, c > e, b > d, d > c e", true); check("a e", "d h", "a b h e f d", "a > b, b > c h, c > d," + "e > f, f > d g, g > h", true); check("a", "h", "a b c h", "a > b i," + "b > a c," + "c > d h," + "d > b e," + "e > f," + "f > g," + "i > j," + "j > i d", true); } public void testDirectPaths() { check("a b", "a c", "a", "", false, true); check("a b", "a c", "a", "", true, true); check("a d f g", "c e", "a d g c e", "a > b e, b > c, d > c, f > d, g > b e h, h > i, i > e", false, true); check("a d f g", "c e", "a d g c e", "a > b e, b > c, d > c, f > d, g > b e h, h > i, i > e", true, true); } private void check(String startVertices, String endVertices, String pathVertices, String graphDescription, boolean shortestOnly) { check(startVertices, endVertices, pathVertices, graphDescription, shortestOnly, false); } private void check(String startVertices, String endVertices, String pathVertices, String graphDescription, boolean shortestOnly, boolean directPathsOnly) { REPOSITORY.clear(); MockVertexCondition startCondition = new MockVertexCondition(createVertices(startVertices)); MockVertexCondition endCondition = new MockVertexCondition(createVertices(endVertices)); PathsFinder pathsFinder = new PathsFinder(startCondition, endCondition, shortestOnly, directPathsOnly); MockVertex[] expectedPaths = createVertices(pathVertices); StringTokenizer tokenizer = new StringTokenizer(graphDescription, ","); while (tokenizer.hasMoreTokens()) { createLinks(tokenizer.nextToken().trim()); } Vertex[] paths = pathsFinder.findPaths(getAllVertices()); HashSet pathNodes = new HashSet(Arrays.asList(paths)); if (expectedPaths.length == pathNodes.size() && expectedPaths.length == paths.length) { for (int i = 0; i < expectedPaths.length; i++) { assertTrue(expectedPaths[i].name + " expected", pathNodes.contains(expectedPaths[i])); } } else { fail("Expected " + Arrays.asList(expectedPaths) + " but was " + Arrays.asList(paths)); } } private MockVertex[] createVertices(String vertexList) { StringTokenizer tokenizer = new StringTokenizer(vertexList); MockVertex[] result = new MockVertex[tokenizer.countTokens()]; for (int i = 0; i < result.length; i++) { result[i] = getVertex(tokenizer.nextToken()); } return result; } private void createLinks(String linkDescription) { StringTokenizer tokenizer = new StringTokenizer(linkDescription, ">"); Vertex startVertex = getVertex(tokenizer.nextToken().trim()); tokenizer = new StringTokenizer(tokenizer.nextToken().trim()); while (tokenizer.hasMoreTokens()) { startVertex.addOutgoingArcTo(getVertex(tokenizer.nextToken())); } } } �����������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/StrongComponentProcessorTest.java�����������������������������0000664�0000000�0000000�00000013633�12021221155�0026611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle.graph; /** * * * @author Franz-Josef Elmer */ public class StrongComponentProcessorTest extends GraphTestCase { public StrongComponentProcessorTest(String s) { super(s); } public void testZeroVertexGraph() { check(new String[0], new int[0][0]); } public void testOneVertexGraphs() { check(new String[] {"0: 0"}, new int[][] {{}}); check(new String[] {"0: 0"}, new int[][] {{0}}); check(new String[] {"0: 0"}, new int[][] {{-1}}); check(new String[] {"0: 0"}, new int[][] {{-1,0}}); check(new String[] {"0: 0"}, new int[][] {{0,-1}}); check(new String[] {"0: 0"}, new int[][] {{-1,0,-1}}); } public void testTwoVerticesGraphs() { check(new String[] {"0: 0 1"}, new int[][] {{1},{0}}); check(new String[] {"0: 0 1"}, new int[][] {{1,0},{0,-1}}); check(new String[] {"0: 0 1"}, new int[][] {{0,1},{0,1}}); check(new String[] {"0: 0","0: 1"}, new int[][] {{},{}}); check(new String[] {"0: 0","0: 1"}, new int[][] {{},{0}}); check(new String[] {"0: 0","0: 1"}, new int[][] {{1},{}}); check(new String[] {"0: 1","0: 0"}, new int[][] {{0},{0,-1}}); } public void testThreeVerticesGraphs() { check(new String[] {"0: 0", "0: 1", "0: 2"}, new int[][] {{},{},{-1}}); check(new String[] {"0: 0", "0: 1", "0: 2"}, new int[][] {{0},{1},{2}}); check(new String[] {"0: 0 1", "0: 2"}, new int[][] {{1},{0},{-1,2}}); check(new String[] {"0: 0 1", "0: 2"}, new int[][] {{1},{0,1},{0}}); check(new String[] {"0: 2", "0: 0 1"}, new int[][] {{1},{0},{0,1}}); check(new String[] {"0: 0 2", "0: 1"}, new int[][] {{-1,2},{0},{-1,0}}); check(new String[] {"0: 0 1 2"}, new int[][] {{2},{0},{1}}); check(new String[] {"0: 0 1 2"}, new int[][] {{2},{0,2},{1}}); check(new String[] {"0: 0 1 2"}, new int[][] {{2},{2,0},{1}}); } public void testComplexGraphs() { check(new String[] {"0: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {1, -1, 4}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"0: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {1, -1, 4}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"0: 0 1 2 3", "0: 4 5"}, new int[][] {{1, 2}, // 0 {0}, // 1 {3, -1, -1}, // 2 {4, -1, 1}, // 3 {5}, // 4 {4}, // 5 }); check(new String[] {"0: 0 1 2 3 6", "0: 4 5", "0: 7"}, new int[][] {{1}, // 0 {2}, // 1 {2, 3, -1, 4}, // 2 {1, -1, 0, 6}, // 3 {5}, // 4 {4}, // 5 {3, 7}, // 6 {-1} // 7 }); } public void testAttributesOfStrongComponent() { StrongComponent[] components = check(new String[] {"0: 0 1 2 3 6", "0: 4 5", "0: 7"}, new int[][] {{1}, // 0 {2}, // 1 {2, 3, -1, 4}, // 2 {1, -1, 0, 6}, // 3 {5}, // 4 {4}, // 5 {3, 7}, // 6 {-1} // 7 }); checkAttributes(new int[] {4, 2, 2, 1, 1, 1, 4, 1}, new int[] {4, 3, 2, 2, 1, 1, 3, 0}, components); components = check(new String[] {"0: 0", "0: 1", "0: 2 6", "0: 4", "0: 3 7 8 9", "0: 5"}, new int[][] {{2}, // 0 {-1}, // 1 {1, 6, -1}, // 2 {7, -1, 4, 9}, // 3 {6}, // 4 {1}, // 5 {2, -1}, // 6 {8, 5, -1}, // 7 {3, -1}, // 8 {3, -1} // 9 }); checkAttributes(new int[] {1, 1, 1, 1, 1, 1, 1, 2, 2, 3}, new int[] {0, 0, 1, 2, 0, 0, 1, 3, 2, 3}, components); } private void checkAttributes(int[] expectedMaximumFragmentSizes, int[] expectedEccentricities, StrongComponent[] components) { for (int i = 0; i < components.length; i++) { StrongComponent component = components[i]; GraphAttributes attributes = (GraphAttributes) component.getAttributes(); for (int j = 0, n = component.getNumberOfVertices(); j < n; j++) { int index = Integer.parseInt(component.getVertex(j) .getAttributes().toString()); assertEquals("eccentricity of vertex " + index, expectedEccentricities[index], n == 1 ? 0 : attributes.getEccentricities()[j]); assertEquals("max fragment size of vertex " + index, expectedMaximumFragmentSizes[index], attributes.getMaximumFragmentSizes()[j]); } } } } �����������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/graph/VertexTest.java�����������������������������������������������0000664�0000000�0000000�00000004275�12021221155�0023031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package classycle.graph; import junit.framework.TestCase; public class VertexTest extends TestCase { public VertexTest(String name) { super(name); } public void testAddOutgoingArc() { Vertex tail = new Vertex(null); Vertex head = new Vertex(null); tail.addOutgoingArcTo(head); assertEquals(0, tail.getNumberOfIncomingArcs()); assertEquals(1, tail.getNumberOfOutgoingArcs()); assertSame(head, tail.getHeadVertex(0)); assertEquals(0, head.getNumberOfOutgoingArcs()); assertEquals(1, head.getNumberOfIncomingArcs()); assertSame(tail, head.getTailVertex(0)); // multiple arcs are not possible tail.addOutgoingArcTo(head); assertEquals(1, tail.getNumberOfOutgoingArcs()); // add second arc Vertex head2 = new Vertex(null); tail.addOutgoingArcTo(head2); assertEquals(0, tail.getNumberOfIncomingArcs()); assertEquals(2, tail.getNumberOfOutgoingArcs()); assertSame(head, tail.getHeadVertex(0)); assertSame(head2, tail.getHeadVertex(1)); } public void testAddIncomingArc() { Vertex head = new Vertex(null); Vertex tail = new Vertex(null); head.addIncomingArcTo(tail); assertEquals(0, head.getNumberOfOutgoingArcs()); assertEquals(1, head.getNumberOfIncomingArcs()); assertSame(tail, head.getTailVertex(0)); assertEquals(0, tail.getNumberOfIncomingArcs()); assertEquals(1, tail.getNumberOfOutgoingArcs()); assertSame(head, tail.getHeadVertex(0)); // multiple arcs are not possible head.addIncomingArcTo(tail); assertEquals(1, head.getNumberOfIncomingArcs()); // add second arc Vertex tail2 = new Vertex(null); head.addIncomingArcTo(tail2); assertEquals(0, head.getNumberOfOutgoingArcs()); assertEquals(2, head.getNumberOfIncomingArcs()); assertSame(tail, head.getTailVertex(0)); assertSame(tail2, head.getTailVertex(1)); } public void testVisit() { Vertex vertex = new Vertex(null); assertTrue(!vertex.isVisited()); vertex.visit(); assertTrue(vertex.isVisited()); vertex.visit(); assertTrue(vertex.isVisited()); vertex.reset(); assertTrue(!vertex.isVisited()); vertex.reset(); assertTrue(!vertex.isVisited()); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/util/���������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0017715�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/util/TextTest.java��������������������������������������������������0000664�0000000�0000000�00000000436�12021221155�0022347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 30.06.2004 */ package classycle.util; import junit.framework.TestCase; /** * @author Franz-Josef Elmer */ public class TextTest extends TestCase { public void testExcapeForXML() { assertEquals("<hel&lo>", Text.excapeForXML("<hel&lo>")); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/classycle/util/WildCardPatternTest.java���������������������������������������0000664�0000000�0000000�00000006376�12021221155�0024463�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Created on 18.06.2004 */ package classycle.util; import junit.framework.TestCase; /** * @author Franz-Josef Elmer */ public class WildCardPatternTest extends TestCase { /** * Constructor for WildCardPatternTest. * @param arg0 */ public WildCardPatternTest(String arg0) { super(arg0); } public void testOnNull() { matchNot("", null); } public void testEmptyPattern() { match("", ""); matchNot("", "a"); } public void testConstantPattern() { match("a", "a"); matchNot("a", ""); matchNot("a", "affe"); matchNot("a", "Kaffee"); matchNot("affe", "a"); } public void testStar() { match("*", ""); match("*", "a"); match("*", "affe"); match("*", "*"); } public void testStartConstant() { match("*t", "t"); match("*t", "Test"); match("*t", "test"); matchNot("*t", "ti"); matchNot("*t", "iti"); match("*te", "te"); match("*te", "ate"); match("*te", "ate"); match("*te", "ateate"); matchNot("*te", "a"); matchNot("*te", "atea"); } public void testConstantStar() { match("t*", "t"); match("t*", "test"); match("t*", "tester"); matchNot("t*", ""); matchNot("t*", "a"); matchNot("t*", "at"); matchNot("t*", "ate"); match("af*", "af"); match("af*", "affe"); match("af*", "affenkaffee"); matchNot("af*", ""); matchNot("af*", "a"); matchNot("af*", "f"); matchNot("af*", "kaffee"); } public void testStarConstan() { match("*t*", "t"); match("*t*", "Test"); match("*t*", "Tester"); match("*t*", "test"); match("*t*", "tester"); matchNot("*t*", ""); matchNot("*t*", "a"); matchNot("*t*", "affe"); } public void testConstantStarConstant() { match("a*e", "ae"); match("a*e", "affe"); match("a*e", "affebande"); matchNot("a*e", ""); matchNot("a*e", "e"); matchNot("a*e", "a"); matchNot("a*e", "af"); matchNot("a*e", "fe"); matchNot("a*e", "affen"); match("a*ea", "aea"); match("a*ea", "area"); match("a*ea", "aeaea"); match("a*ea", "area in area"); matchNot("a*ea", ""); matchNot("a*ea", "areas"); matchNot("a*ea", "aean"); matchNot("a*ea", "in area"); } public void testStarConstantStarConstant() { match("*a*e", "ae"); match("*a*e", "are"); match("*a*e", "tae"); match("*a*e", "tare"); match("*a*e", "tare ware"); matchNot("*a*e", ""); matchNot("*a*e", "a"); matchNot("*a*e", "e"); matchNot("*a*e", "aeaet"); matchNot("*a*e", "teaer"); matchNot("*a*e", "aaet"); matchNot("*a*e", "are?"); match("*a*a", "aa"); match("*a*a", "aaa"); match("*a*a", "taa"); match("*a*a", "tata"); match("*a*a", "taatata"); matchNot("*a*a", ""); matchNot("*a*a", "a"); matchNot("*a*a", "ra"); matchNot("*a*a", "raarar"); } private void match(String pattern, String string) { assertTrue("'" + string + "' expected to match '" + pattern + "'", new WildCardPattern(pattern).matches(string)); } private void matchNot(String pattern, String string) { assertTrue("'" + string + "' expected not match '" + pattern + "'", !new WildCardPattern(pattern).matches(string)); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0016411�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/A.java����������������������������������������������������������������0000664�0000000�0000000�00000000073�12021221155�0017434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package example; public class A { String s = "hello"; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/AA.java���������������������������������������������������������������0000664�0000000�0000000�00000000132�12021221155�0017531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package example; public class AA { A _a; public void setA(A a) { _a = a; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/B.java����������������������������������������������������������������0000664�0000000�0000000�00000000277�12021221155�0017443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package example; public class B extends BofA { class M implements example.p.A { public A getA() { return null; } } public A getA() { return new A(); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/BofA.java�������������������������������������������������������������0000664�0000000�0000000�00000000161�12021221155�0020061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package example; import example.p.A; public abstract class BofA implements A { Class clazz = Thread.class; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/p/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�12021221155�0016650�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������classycle-1.4/srcTest/example/p/A.java��������������������������������������������������������������0000664�0000000�0000000�00000000106�12021221155�0017670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������package example.p; public interface A { public example.A getA(); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������