How to eliminate cyclic dependencies
authorJaroslav Tulach <jtulach@netbeans.org>
Sat, 14 Jun 2008 09:53:48 +0200
changeset 87618b79994cd4
parent 86 adf4440db888
child 88 97d71053c1a8
How to eliminate cyclic dependencies
samples/preventcyclicdependencies/build.xml
samples/preventcyclicdependencies/nbproject/project.xml
samples/preventcyclicdependencies/src-acyclic1/org/apidesign/cycles/array/MutableArray.java
samples/preventcyclicdependencies/src-acyclic2/META-INF/services/org.apidesign.cycles.array.MutableArray$DoEncode
samples/preventcyclicdependencies/src-acyclic2/org/apidesign/cycles/crypt/DoEncodeImpl.java
samples/preventcyclicdependencies/src-acyclic2/org/apidesign/cycles/crypt/Encryptor.java
samples/preventcyclicdependencies/src-cyclic/org/apidesign/cycles/array/MutableArray.java
samples/preventcyclicdependencies/src-cyclic/org/apidesign/cycles/crypt/Encryptor.java
samples/preventcyclicdependencies/src-test/org/apidesign/cycles/array/test/Main.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/samples/preventcyclicdependencies/build.xml	Sat Jun 14 09:53:48 2008 +0200
     1.3 @@ -0,0 +1,67 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<project name="preventcyclicdependencies" default="run" basedir=".">
     1.6 +    <target name="clean">
     1.7 +        <delete dir="build"/>
     1.8 +    </target>
     1.9 +    
    1.10 +    <target name="build">
    1.11 +        <antcall target="-build-one">
    1.12 +            <param name="version" value="cyclic"/>
    1.13 +        </antcall>
    1.14 +        <antcall target="-build-one">
    1.15 +            <param name="version" value="test"/>
    1.16 +            <param name="cp" location="build/cyclic/classes"/>
    1.17 +        </antcall>
    1.18 +        <antcall target="-build-one">
    1.19 +            <param name="version" value="acyclic1"/>
    1.20 +        </antcall>
    1.21 +        <antcall target="-build-one">
    1.22 +            <param name="version" value="acyclic2"/>
    1.23 +            <param name="cp" location="build/acyclic1/classes"/>
    1.24 +        </antcall>
    1.25 +    </target>
    1.26 +    
    1.27 +    <target name="run" depends="build">
    1.28 +        <echo level="info" message="Running old API with cycles between packages:"/>
    1.29 +        <antcall target="-run-one">
    1.30 +            <param name="version1" value="cyclic"/>
    1.31 +        </antcall>
    1.32 +        <echo level="info" message="Running new API without cycles:"/>
    1.33 +        <antcall target="-run-one">
    1.34 +            <param name="version1" value="acyclic1"/>
    1.35 +            <param name="version2" value="acyclic2"/>
    1.36 +        </antcall>
    1.37 +    </target>
    1.38 +
    1.39 +    
    1.40 +    <!-- support methods -->
    1.41 +    
    1.42 +    <target name="-run-one">
    1.43 +        <java 
    1.44 +            classpath="build/${version1}/classes:build/${version2}/classes:build/test/classes:../libs/dist/org-openide-util.jar" 
    1.45 +            classname="org.apidesign.cycles.array.test.Main"
    1.46 +            failonerror="true" 
    1.47 +        >
    1.48 +            <jvmarg value="-ea"/>
    1.49 +        </java>
    1.50 +    </target>
    1.51 +    
    1.52 +    <target name="-build-one">
    1.53 +        <fail message="You need to specify version number" unless="version"/>
    1.54 +        
    1.55 +        <mkdir dir="build/${version}/classes"/>
    1.56 +        <property name="cp" value=""/>
    1.57 +        <javac 
    1.58 +            srcdir="src-${version}" 
    1.59 +            destdir="build/${version}/classes" 
    1.60 +            source="1.5" target="1.5"
    1.61 +            debug="true"
    1.62 +            classpath="${cp}"
    1.63 +        />
    1.64 +        <copy todir="build/${version}/classes">
    1.65 +            <fileset dir="src-${version}">
    1.66 +                <exclude name="**/*.java"/>
    1.67 +            </fileset>
    1.68 +        </copy>
    1.69 +    </target>
    1.70 +</project>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/samples/preventcyclicdependencies/nbproject/project.xml	Sat Jun 14 09:53:48 2008 +0200
     2.3 @@ -0,0 +1,116 @@
     2.4 +<?xml version="1.0" encoding="UTF-8"?>
     2.5 +<project xmlns="http://www.netbeans.org/ns/project/1" xmlns:ns4="null">
     2.6 +    <type>org.netbeans.modules.ant.freeform</type>
     2.7 +    <configuration>
     2.8 +        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
     2.9 +            <name>preventcyclicdependencies</name>
    2.10 +        </general-data>
    2.11 +        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/2">
    2.12 +            <!-- Do not use Project Properties customizer when editing this file manually. -->
    2.13 +            <name>preventcyclicdependencies</name>
    2.14 +            <properties/>
    2.15 +            <folders>
    2.16 +                <source-folder>
    2.17 +                    <label>preventcyclicdependencies</label>
    2.18 +                    <location>.</location>
    2.19 +                    <encoding>UTF-8</encoding>
    2.20 +                </source-folder>
    2.21 +                <source-folder>
    2.22 +                    <label>src-cyclic</label>
    2.23 +                    <type>java</type>
    2.24 +                    <location>src-cyclic</location>
    2.25 +                    <encoding>UTF-8</encoding>
    2.26 +                </source-folder>
    2.27 +                <source-folder>
    2.28 +                    <label>src-test</label>
    2.29 +                    <type>java</type>
    2.30 +                    <location>src-test</location>
    2.31 +                    <encoding>UTF-8</encoding>
    2.32 +                </source-folder>
    2.33 +                <source-folder>
    2.34 +                    <label>src-acyclic1</label>
    2.35 +                    <type>java</type>
    2.36 +                    <location>src-acyclic1</location>
    2.37 +                    <encoding>UTF-8</encoding>
    2.38 +                </source-folder>
    2.39 +                <source-folder>
    2.40 +                    <label>src-acyclic2</label>
    2.41 +                    <type>java</type>
    2.42 +                    <location>src-acyclic2</location>
    2.43 +                    <encoding>UTF-8</encoding>
    2.44 +                </source-folder>
    2.45 +            </folders>
    2.46 +            <ide-actions>
    2.47 +                <action name="build">
    2.48 +                    <target>build</target>
    2.49 +                </action>
    2.50 +                <action name="clean">
    2.51 +                    <target>clean</target>
    2.52 +                </action>
    2.53 +                <action name="run">
    2.54 +                    <target>run</target>
    2.55 +                </action>
    2.56 +                <action name="rebuild">
    2.57 +                    <target>clean</target>
    2.58 +                    <target>build</target>
    2.59 +                </action>
    2.60 +            </ide-actions>
    2.61 +            <view>
    2.62 +                <items>
    2.63 +                    <source-folder style="packages">
    2.64 +                        <label>src-cyclic</label>
    2.65 +                        <location>src-cyclic</location>
    2.66 +                    </source-folder>
    2.67 +                    <source-folder style="packages">
    2.68 +                        <label>src-test</label>
    2.69 +                        <location>src-test</location>
    2.70 +                    </source-folder>
    2.71 +                    <source-folder style="packages">
    2.72 +                        <label>src-acyclic1</label>
    2.73 +                        <location>src-acyclic1</location>
    2.74 +                    </source-folder>
    2.75 +                    <source-folder style="packages">
    2.76 +                        <label>src-acyclic2</label>
    2.77 +                        <location>src-acyclic2</location>
    2.78 +                    </source-folder>
    2.79 +                    <source-file>
    2.80 +                        <location>build.xml</location>
    2.81 +                    </source-file>
    2.82 +                </items>
    2.83 +                <context-menu>
    2.84 +                    <ide-action name="build"/>
    2.85 +                    <ide-action name="rebuild"/>
    2.86 +                    <ide-action name="clean"/>
    2.87 +                    <ide-action name="run"/>
    2.88 +                    <ide-action name="debug"/>
    2.89 +                </context-menu>
    2.90 +            </view>
    2.91 +            <subprojects/>
    2.92 +        </general-data>
    2.93 +        <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/1">
    2.94 +            <compilation-unit>
    2.95 +                <package-root>src-cyclic</package-root>
    2.96 +                <built-to>build/cyclic/classes</built-to>
    2.97 +                <source-level>1.5</source-level>
    2.98 +            </compilation-unit>
    2.99 +            <compilation-unit>
   2.100 +                <package-root>src-test</package-root>
   2.101 +                <classpath mode="compile">src-cyclic</classpath>
   2.102 +                <built-to>build/test/classes</built-to>
   2.103 +                <source-level>1.5</source-level>
   2.104 +            </compilation-unit>
   2.105 +            <compilation-unit>
   2.106 +                <package-root>src-acyclic1</package-root>
   2.107 +                <classpath mode="compile">../libs/dist/org-openide-util.jar</classpath>
   2.108 +                <built-to>build/acyclic1/classes</built-to>
   2.109 +                <source-level>1.5</source-level>
   2.110 +            </compilation-unit>
   2.111 +            <compilation-unit>
   2.112 +                <package-root>src-acyclic2</package-root>
   2.113 +                <classpath mode="compile">src-acyclic1</classpath>
   2.114 +                <built-to>build/acyclic2/classes</built-to>
   2.115 +                <source-level>1.5</source-level>
   2.116 +            </compilation-unit>
   2.117 +        </java-data>
   2.118 +    </configuration>
   2.119 +</project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/samples/preventcyclicdependencies/src-acyclic1/org/apidesign/cycles/array/MutableArray.java	Sat Jun 14 09:53:48 2008 +0200
     3.3 @@ -0,0 +1,38 @@
     3.4 +package org.apidesign.cycles.array;
     3.5 +
     3.6 +import java.io.IOException;
     3.7 +import java.io.OutputStream;
     3.8 +import org.openide.util.Lookup;
     3.9 +// BEGIN: nocycles.ma2
    3.10 +public class MutableArray {
    3.11 +    private byte[] arr;
    3.12 +
    3.13 +    public MutableArray(byte[] arr) {
    3.14 +        this.arr = arr;
    3.15 +    }
    3.16 +
    3.17 +    public void xor(byte b) {
    3.18 +        for (int i = 0; i < arr.length; i++) { arr[i] ^= b; }
    3.19 +    }
    3.20 +
    3.21 +    public void and(byte b) {
    3.22 +        for (int i = 0; i < arr.length; i++) { arr[i] &= b; }
    3.23 +    }
    3.24 +
    3.25 +    public void or(byte b) {
    3.26 +        for (int i = 0; i < arr.length; i++) { arr[i] |= b; }
    3.27 +    }
    3.28 +
    3.29 +    public void encrypt(OutputStream os) throws IOException {
    3.30 +        DoEncode en = Lookup.getDefault().lookup(DoEncode.class);
    3.31 +        assert en != null : "We need org.netbeans.example.crypt to be enabled!";
    3.32 +        byte[] clone = (byte[]) arr.clone();
    3.33 +        en.encode(clone);
    3.34 +        os.write(clone);
    3.35 +    }
    3.36 +    
    3.37 +    public interface DoEncode {
    3.38 +        public void encode(byte[] arr);
    3.39 +    }
    3.40 +}
    3.41 +// END: nocycles.ma2
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/samples/preventcyclicdependencies/src-acyclic2/META-INF/services/org.apidesign.cycles.array.MutableArray$DoEncode	Sat Jun 14 09:53:48 2008 +0200
     4.3 @@ -0,0 +1,1 @@
     4.4 +org.apidesign.cycles.crypt.DoEncodeImpl
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/samples/preventcyclicdependencies/src-acyclic2/org/apidesign/cycles/crypt/DoEncodeImpl.java	Sat Jun 14 09:53:48 2008 +0200
     5.3 @@ -0,0 +1,12 @@
     5.4 +// BEGIN: nocycles.encrypt2
     5.5 +package org.apidesign.cycles.crypt;
     5.6 +
     5.7 +import org.apidesign.cycles.array.MutableArray;
     5.8 +
     5.9 +public class DoEncodeImpl implements MutableArray.DoEncode {
    5.10 +    public void encode(byte[] arr) {
    5.11 +        Encryptor en = new Encryptor();
    5.12 +        en.encode(arr);
    5.13 +    }
    5.14 +}
    5.15 +// END: nocycles.encrypt2
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/samples/preventcyclicdependencies/src-acyclic2/org/apidesign/cycles/crypt/Encryptor.java	Sat Jun 14 09:53:48 2008 +0200
     6.3 @@ -0,0 +1,10 @@
     6.4 +package org.apidesign.cycles.crypt;
     6.5 +
     6.6 +import org.apidesign.cycles.array.MutableArray;
     6.7 +
     6.8 +public final class Encryptor {
     6.9 +    public void encode(byte[] arr) {
    6.10 +        MutableArray m = new MutableArray(arr);
    6.11 +        m.xor((byte)0x3d);
    6.12 +    }
    6.13 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/samples/preventcyclicdependencies/src-cyclic/org/apidesign/cycles/array/MutableArray.java	Sat Jun 14 09:53:48 2008 +0200
     7.3 @@ -0,0 +1,35 @@
     7.4 +// BEGIN: cycles.ma1
     7.5 +package org.apidesign.cycles.array;
     7.6 +
     7.7 +import java.io.IOException;
     7.8 +import java.io.OutputStream;
     7.9 +import org.apidesign.cycles.crypt.Encryptor;
    7.10 +
    7.11 +public class MutableArray {
    7.12 +    private byte[] arr;
    7.13 +
    7.14 +    public MutableArray(byte[] arr) {
    7.15 +        this.arr = arr;
    7.16 +    }
    7.17 +
    7.18 +    public void xor(byte b) {
    7.19 +        for (int i = 0; i < arr.length; i++) { arr[i] ^= b; }
    7.20 +    }
    7.21 +
    7.22 +    public void and(byte b) {
    7.23 +        for (int i = 0; i < arr.length; i++) { arr[i] &= b; }
    7.24 +    }
    7.25 +
    7.26 +    public void or(byte b) {
    7.27 +        for (int i = 0; i < arr.length; i++) { arr[i] |= b; }
    7.28 +    }
    7.29 +
    7.30 +    public void encrypt(OutputStream os) throws IOException {
    7.31 +        Encryptor en = new Encryptor();
    7.32 +        byte[] clone = (byte[]) arr.clone();
    7.33 +        en.encode(clone);
    7.34 +        os.write(clone);
    7.35 +    }
    7.36 +}
    7.37 +// END: cycles.ma1
    7.38 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/samples/preventcyclicdependencies/src-cyclic/org/apidesign/cycles/crypt/Encryptor.java	Sat Jun 14 09:53:48 2008 +0200
     8.3 @@ -0,0 +1,12 @@
     8.4 +// BEGIN: cycles.encryptor1
     8.5 +package org.apidesign.cycles.crypt;
     8.6 +
     8.7 +import org.apidesign.cycles.array.MutableArray;
     8.8 +
     8.9 +public final class Encryptor {
    8.10 +    public void encode(byte[] arr) {
    8.11 +        MutableArray m = new MutableArray(arr);
    8.12 +        m.xor((byte)0x3d);
    8.13 +    }
    8.14 +}
    8.15 +// END: cycles.encryptor1
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/samples/preventcyclicdependencies/src-test/org/apidesign/cycles/array/test/Main.java	Sat Jun 14 09:53:48 2008 +0200
     9.3 @@ -0,0 +1,29 @@
     9.4 +package org.apidesign.cycles.array.test;
     9.5 +
     9.6 +import org.apidesign.cycles.array.*;
     9.7 +import java.io.ByteArrayOutputStream;
     9.8 +import java.io.IOException;
     9.9 +import java.io.OutputStream;
    9.10 +import org.apidesign.cycles.crypt.Encryptor;
    9.11 +
    9.12 +public class Main {
    9.13 +    public static void main(String[] args) throws Exception {
    9.14 +        byte[] five = { 1, 2, 3, 4, 5 };
    9.15 +        MutableArray arr = new MutableArray(five);
    9.16 +        
    9.17 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
    9.18 +        arr.encrypt(os);
    9.19 +        
    9.20 +        byte[] out = os.toByteArray();
    9.21 +        assert out.length == 5;
    9.22 +        
    9.23 +        for (int i = 0; i < 5; i++) {
    9.24 +            int exp = five[i] ^ 0x3d;
    9.25 +            if (exp != out[i]) {
    9.26 +                assert false : "Index: " + i + " exp: " + exp + " was: " + out[i];
    9.27 +            }
    9.28 +        }
    9.29 +        System.err.println("OK");
    9.30 +    }
    9.31 +}
    9.32 +