11.10 Map
This commit is contained in:
13
.idea/Thinking in Java源代码.iml
generated
Normal file
13
.idea/Thinking in Java源代码.iml
generated
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<output url="file:///production/Thinking in Java源代码" />
|
||||||
|
<output-test url="file:///test/Thinking in Java源代码" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
36
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
36
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="TOP_LEVEL_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="INNER_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="METHOD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="FIELD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="IGNORE_DEPRECATED" value="false" />
|
||||||
|
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
|
||||||
|
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
|
||||||
|
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
|
||||||
|
<option name="myAdditionalJavadocTags" value="date" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/Thinking in Java源代码.iml" filepath="$PROJECT_DIR$/.idea/Thinking in Java源代码.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
66
Copyright.txt
Normal file
66
Copyright.txt
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
This computer source code is Copyright (c)2006 MindView, Inc.
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this
|
||||||
|
computer source code (Source Code) and its documentation
|
||||||
|
without fee and without a written agreement for the
|
||||||
|
purposes set forth below is hereby granted, provided that
|
||||||
|
the above copyright notice, this paragraph and the
|
||||||
|
following five numbered paragraphs appear in all copies.
|
||||||
|
|
||||||
|
1. Permission is granted to compile the Source Code and to
|
||||||
|
include the compiled code, in executable format only, in
|
||||||
|
personal and commercial software programs.
|
||||||
|
|
||||||
|
2. Permission is granted to use the Source Code without
|
||||||
|
modification in classroom situations, including in
|
||||||
|
presentation materials, provided that the book "Thinking in
|
||||||
|
Java" is cited as the origin.
|
||||||
|
|
||||||
|
3. Permission to incorporate the Source Code into printed
|
||||||
|
media may be obtained by contacting:
|
||||||
|
|
||||||
|
MindView, Inc. 5343 Valle Vista La Mesa, California 91941
|
||||||
|
Wayne@MindView.net
|
||||||
|
|
||||||
|
4. The Source Code and documentation are copyrighted by
|
||||||
|
MindView, Inc. The Source code is provided without express
|
||||||
|
or implied warranty of any kind, including any implied
|
||||||
|
warranty of merchantability, fitness for a particular
|
||||||
|
purpose or non-infringement. MindView, Inc. does not
|
||||||
|
warrant that the operation of any program that includes the Source Code will be uninterrupted or error-free. MindView,
|
||||||
|
Inc. makes no representation about the suitability of the
|
||||||
|
Source Code or of any software that includes the Source
|
||||||
|
Code for any purpose. The entire risk as to the quality
|
||||||
|
and performance of any program that includes the Source
|
||||||
|
Code is with the user of the Source Code. The user
|
||||||
|
understands that the Source Code was developed for research and instructional purposes and is advised not to rely
|
||||||
|
exclusively for any reason on the Source Code or any
|
||||||
|
program that includes the Source Code. Should the Source
|
||||||
|
Code or any resulting software prove defective, the user
|
||||||
|
assumes the cost of all necessary servicing, repair, or
|
||||||
|
correction.
|
||||||
|
|
||||||
|
5. IN NO EVENT SHALL MINDVIEW, INC., OR ITS PUBLISHER BE
|
||||||
|
LIABLE TO ANY PARTY UNDER ANY LEGAL THEORY FOR DIRECT,
|
||||||
|
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||||
|
INCLUDING LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF
|
||||||
|
BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS, OR FOR
|
||||||
|
PERSONAL INJURIES, ARISING OUT OF THE USE OF THIS SOURCE
|
||||||
|
CODE AND ITS DOCUMENTATION, OR ARISING OUT OF THE INABILITY TO USE ANY RESULTING PROGRAM, EVEN IF MINDVIEW, INC., OR
|
||||||
|
ITS PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGE. MINDVIEW, INC. SPECIFICALLY DISCLAIMS ANY
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOURCE CODE AND DOCUMENTATION PROVIDED
|
||||||
|
HEREUNDER IS ON AN "AS IS" BASIS, WITHOUT ANY ACCOMPANYING
|
||||||
|
SERVICES FROM MINDVIEW, INC., AND MINDVIEW, INC. HAS NO
|
||||||
|
OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||||
|
ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
Please note that MindView, Inc. maintains a Web site which
|
||||||
|
is the sole distribution point for electronic copies of the Source Code, http://www.MindView.net (and official mirror
|
||||||
|
sites), where it is freely available under the terms stated above.
|
||||||
|
|
||||||
|
If you think you've found an error in the Source Code,
|
||||||
|
please submit a correction using the feedback system that you will find at http://www.MindView.net.
|
||||||
25
DEclipse.py
Normal file
25
DEclipse.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
DEclipse.py by Bruce Eckel, for Thinking in Java 4e
|
||||||
|
|
||||||
|
Undoes the effect of Eclipse.py, so that Ant can be used
|
||||||
|
again to build the code tree.
|
||||||
|
|
||||||
|
You must have Python 2.3 installed to run this program. See www.python.org.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
for path, dirs, files in os.walk('.'):
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(".java"):
|
||||||
|
filepath = path + os.sep + file
|
||||||
|
code = open(filepath).readlines()
|
||||||
|
found = False
|
||||||
|
for n, line in enumerate(code):
|
||||||
|
if line.find(" /* Added by Eclipse.py */") != -1:
|
||||||
|
del code[n]
|
||||||
|
open(filepath, 'w').writelines(code)
|
||||||
|
|
||||||
|
|
||||||
|
print "Project ready to be built with Ant."
|
||||||
|
|
||||||
115
Eclipse.py
Normal file
115
Eclipse.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
Eclipse.py by Bruce Eckel, for Thinking in Java 4e
|
||||||
|
Modify or insert package statments so that Eclipse is happy with the code tree.
|
||||||
|
Run this with no arguments from the root of the code tree.
|
||||||
|
|
||||||
|
The Ant build will not work once you run this program!
|
||||||
|
|
||||||
|
You may also want to modify the dotproject and dotclasspath text below.
|
||||||
|
|
||||||
|
You must have Python 2.3 installed to run this program. See www.python.org.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
os.remove("reusing/Lisa.java");
|
||||||
|
|
||||||
|
for path, dirs, files in os.walk('.'):
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(".java"):
|
||||||
|
filepath = path + os.sep + file
|
||||||
|
firstLine = open(filepath).readline().strip()
|
||||||
|
tagPath = firstLine.split()[1]
|
||||||
|
tagPath = ".".join(tagPath.split('/')[:-1])
|
||||||
|
packageStatement = "package " + tagPath + ";"
|
||||||
|
code = open(filepath).readlines()
|
||||||
|
found = False
|
||||||
|
for line in code:
|
||||||
|
if line.startswith("package "):
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
code.insert(1, packageStatement + " /* Added by Eclipse.py */\n")
|
||||||
|
open(filepath, 'w').writelines(code)
|
||||||
|
|
||||||
|
here = os.path.abspath('.').replace("\\", "/")
|
||||||
|
if here.startswith("/cygdrive/"): # If using cygwin
|
||||||
|
here = here.replace("/cygdrive/", "", 1)
|
||||||
|
here = here[0] + ":" + here[1:]
|
||||||
|
print "here", here
|
||||||
|
open(".classpath", 'w').write(\
|
||||||
|
"""<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry excluding="polymorphism/|holding/|flow/|exceptions/|concurrency/|typeinfo/|innerclasses/|arrays/|interfaces/|reusing/|initialization/|cloning/|io/|containers/|generics/|xml/|hiding/|io/xfiles/|passing/|gui/|annotations/|enumerated/|discovering/|object/|strings/|swt/" kind="src" path=""/>
|
||||||
|
<classpathentry kind="src" path="annotations"/>
|
||||||
|
<classpathentry kind="src" path="arrays"/>
|
||||||
|
<classpathentry kind="src" path="cloning"/>
|
||||||
|
<classpathentry kind="src" path="concurrency"/>
|
||||||
|
<classpathentry kind="src" path="containers"/>
|
||||||
|
<classpathentry kind="src" path="discovering"/>
|
||||||
|
<classpathentry kind="src" path="enumerated"/>
|
||||||
|
<classpathentry kind="src" path="exceptions"/>
|
||||||
|
<classpathentry kind="src" path="flow"/>
|
||||||
|
<classpathentry kind="src" path="generics"/>
|
||||||
|
<classpathentry kind="src" path="gui"/>
|
||||||
|
<classpathentry kind="src" path="hiding"/>
|
||||||
|
<classpathentry kind="src" path="holding"/>
|
||||||
|
<classpathentry kind="src" path="initialization"/>
|
||||||
|
<classpathentry kind="src" path="innerclasses"/>
|
||||||
|
<classpathentry kind="src" path="interfaces"/>
|
||||||
|
<classpathentry excluding="xfiles/" kind="src" path="io"/>
|
||||||
|
<classpathentry kind="src" path="io/xfiles"/>
|
||||||
|
<classpathentry kind="src" path="object"/>
|
||||||
|
<classpathentry kind="src" path="passing"/>
|
||||||
|
<classpathentry kind="src" path="polymorphism"/>
|
||||||
|
<classpathentry kind="src" path="reusing"/>
|
||||||
|
<classpathentry kind="src" path="strings"/>
|
||||||
|
<classpathentry kind="src" path="swt"/>
|
||||||
|
<classpathentry kind="src" path="typeinfo"/>
|
||||||
|
<classpathentry kind="src" path="xml"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jre1.5.0_01"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
|
""") # % (here, here))
|
||||||
|
|
||||||
|
open(".project", 'w').write(\
|
||||||
|
"""<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>TIJ4</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
if not os.path.exists(".settings"):
|
||||||
|
os.mkdir(".settings")
|
||||||
|
os.chdir(".settings")
|
||||||
|
open("org.eclipse.jdt.core.prefs", 'w').write(\
|
||||||
|
"""#Fri Jan 14 11:03:37 MST 2005
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
""")
|
||||||
|
|
||||||
|
print """Project ready to be opened with Eclipse (see www.Eclipse.org)
|
||||||
|
Use DEclipse.py if you want to go back to building with Ant."""
|
||||||
|
|
||||||
53
FindBugsExcluder.py
Normal file
53
FindBugsExcluder.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
"""FindBugsExcluder.py
|
||||||
|
Creates a filter file from the xml and text output of FindBugs
|
||||||
|
To prepare, you must run
|
||||||
|
findbugs -textui . > findbugs.txt
|
||||||
|
findbugs -textui -xml . > findbugs.xml
|
||||||
|
Once you've run this program you can then run
|
||||||
|
findbugs -textui -exclude FindBugsFilter-auto.xml .
|
||||||
|
To exclude the bugs that have been discovered.
|
||||||
|
|
||||||
|
The program includes the suggested changes with each exclusion,
|
||||||
|
so you can go through FindBugsFilter-auto.xml and decide
|
||||||
|
to fix things and remove their "Match" nodes.
|
||||||
|
"""
|
||||||
|
from xml.dom.minidom import parse
|
||||||
|
import xml.dom
|
||||||
|
import os, sys, re, pprint
|
||||||
|
|
||||||
|
xml_buglist = 'findbugs.xml' #'D:\\aaa-TIJ4\\code\\findbugs.xml'
|
||||||
|
text_buglist = 'findbugs.txt' # 'D:\\aaa-TIJ4\\code\\findbugs.txt'
|
||||||
|
findbugs_filter = 'FindBugsFilter-auto.xml' # 'D:\\aaa-TIJ4\\code\\FindBugsFilter-auto.xml'
|
||||||
|
|
||||||
|
def main():
|
||||||
|
textbugs = [bug.split(':', 1) for bug in file(text_buglist)
|
||||||
|
if bug.startswith("M ") or bug.startswith("H ")]
|
||||||
|
textbugs = [(bug[0].split()[2], bug[1].strip()) for bug in textbugs]
|
||||||
|
dom1 = parse(xml_buglist)
|
||||||
|
dom2 = xml.dom.getDOMImplementation().createDocument(
|
||||||
|
None, "FindBugsFilter", None)
|
||||||
|
bugsDone = []
|
||||||
|
for bugNode in [bug for bug in dom1.firstChild.childNodes
|
||||||
|
if bug.nodeName == "BugInstance"]:
|
||||||
|
for child in bugNode.childNodes:
|
||||||
|
if child.nodeName == "Class":
|
||||||
|
classname = child.attributes.item(0).value
|
||||||
|
bugtype = bugNode.attributes.item(2).value
|
||||||
|
if (bugtype, classname) in bugsDone:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
bugsDone.append((bugtype, classname))
|
||||||
|
match = dom2.createElement("Match")
|
||||||
|
match.setAttribute("class", classname)
|
||||||
|
bugCode = dom2.createElement("BugCode")
|
||||||
|
bugCode.setAttribute("name", bugtype)
|
||||||
|
match.appendChild(bugCode)
|
||||||
|
for textbug in textbugs:
|
||||||
|
if textbug[0] == bugtype and classname in textbug[1]:
|
||||||
|
match.appendChild(dom2.createComment(textbug[1]))
|
||||||
|
dom2.documentElement.appendChild(match)
|
||||||
|
break # out of inner for loop
|
||||||
|
file(findbugs_filter, 'w').write(dom2.toprettyxml(' ', '\n'))
|
||||||
|
|
||||||
|
if __name__ == "__main__": main()
|
||||||
|
|
||||||
547
FindBugsFilter.xml
Normal file
547
FindBugsFilter.xml
Normal file
@@ -0,0 +1,547 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<FindBugsFilter>
|
||||||
|
<Match class="AUnitExample2">
|
||||||
|
<BugCode name="OS"/>
|
||||||
|
<!--AUnitExample2.exceptionExample() may fail to close stream At AUnitExample2.java:[line 21]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="BangBean2">
|
||||||
|
<BugCode name="IS2"/>
|
||||||
|
<!--Inconsistent synchronization of BangBean2.fontSize; locked 66% of time Unsynchronized access at BangBean2.java:[line 74]-->
|
||||||
|
<!--Inconsistent synchronization of BangBean2.tColor; locked 66% of time Unsynchronized access at BangBean2.java:[line 73]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Beetle">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Beetle.main(String[]) At Beetle.java:[line 30]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="BerryBrokers$1">
|
||||||
|
<BugCode name="DE"/>
|
||||||
|
<!--BerryBrokers$1.<clinit>() might ignore java.lang.NoSuchFieldError At Thwonk.java:[line 90]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="BigEgg$Yolk">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should BigEgg$Yolk be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Bird">
|
||||||
|
<BugCode name="UuF"/>
|
||||||
|
<!--Unused field: Bird.i-->
|
||||||
|
</Match>
|
||||||
|
<Match class="BlankFinal">
|
||||||
|
<BugCode name="SS"/>
|
||||||
|
<!--Unread field: BlankFinal.i; should this field be static?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Blip2">
|
||||||
|
<BugCode name="Se"/>
|
||||||
|
<!--Blip2 is Externalizable but doesn't define a void constructor-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ButtonGroups">
|
||||||
|
<BugCode name="REC"/>
|
||||||
|
<!--Method ButtonGroups.makeBPanel(Class,String[]) catches Exception, but Exception is not thrown in the try block and RuntimeException is not explicitly caught At ButtonGroups.java:[line 29]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Card">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Card.t1-->
|
||||||
|
<!--Unread field: Card.t2-->
|
||||||
|
<!--Unread field: Card.t3-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Cartoon">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Cartoon.main(String[]) At Cartoon.java:[line 16]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Casting">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Casting.main(String[]) At Casting.java:[line 11]-->
|
||||||
|
<!--Dead store to local variable in method ClassCasting.main(String[]) At ClassCasting.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="CheckCloneable">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method CheckCloneable.main(String[]) At CheckCloneable.java:[line 81]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Chef">
|
||||||
|
<BugCode name="UW"/>
|
||||||
|
<!--Unconditional wait in Chef.run() At Restaurant.java:[line 45]-->
|
||||||
|
<!--(It's not clear to me why this is a problem. I think it's a false positive)-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Chess">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Chess.main(String[]) At Chess.java:[line 24]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ChocolateChip">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method ChocolateChip.main(String[]) At ChocolateChip.java:[line 10]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ClassAsFactory">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: ClassAsFactory.x-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ClassCasting">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method ClassCasting.main(String[]) At ClassCasting.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="CloseResource">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method CloseResource.main(String[]) At CloseResource.java:[line 12]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="CovariantGenerics">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method CovariantGenerics.main(String[]) At CovariantGenerics.java:[line 11]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Cupboard">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Cupboard.b3-->
|
||||||
|
</Match>
|
||||||
|
<Match class="DefaultConstructor">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method DefaultConstructor.main(String[]) At DefaultConstructor.java:[line 9]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Dinner">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Dinner.main(String[]) At Dinner.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Dinosaur">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Dinosaur.i-->
|
||||||
|
<!--Unread field: Dinosaur.x-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Egg">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Egg.y-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Egg$Yolk">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should BigEgg$Yolk be a _static_ inner class?-->
|
||||||
|
<!--Should Egg$Yolk be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<!-------- Checked to here ------------------------------------------------->
|
||||||
|
<Match class="Equivalence">
|
||||||
|
<BugCode name="RC"/>
|
||||||
|
<!--Suspicious comparison of java.lang.Integer references in Equivalence.main(String[]) At Equivalence.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Faces">
|
||||||
|
<BugCode name="UI"/>
|
||||||
|
<!--Usage of GetResource in Faces.<init>() may be unsafe if class is extended At Faces.java:[line 13]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="FillTest">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method FillTest.main(String[]) At Fill.java:[line 40]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="FinalArguments">
|
||||||
|
<BugCode name="IP"/>
|
||||||
|
<!--A parameter to FinalArguments.without(Gizmo) is dead upon entry but overwritten At FinalArguments.java:[line 13]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="FinalData">
|
||||||
|
<BugCode name="SS"/>
|
||||||
|
<!--Unread field: FinalData.valueOne; should this field be static?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="FinalData">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: FinalData.v1-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Foo2">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Foo2.x-->
|
||||||
|
</Match>
|
||||||
|
<Match class="GreenhouseControls">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: GreenhouseControls.light-->
|
||||||
|
<!--Unread field: GreenhouseControls.thermostat-->
|
||||||
|
<!--Unread field: GreenhouseControls.water-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Holder">
|
||||||
|
<BugCode name="EC"/>
|
||||||
|
<!--Call to equals() comparing different types in Holder.main(String[]) At Holder.java:[line 28]-->
|
||||||
|
<!--Call to equals() comparing different types in WildcardRules.f(Holder) At WildcardRules.java:[line 11]-->
|
||||||
|
<!--Call to equals() comparing different types in WildcardRules.g(Holder) At WildcardRules.java:[line 17]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Holder">
|
||||||
|
<BugCode name="HE"/>
|
||||||
|
<!--Holder defines equals and uses Object.hashCode()-->
|
||||||
|
</Match>
|
||||||
|
<Match class="IInterface$Inner">
|
||||||
|
<BugCode name="UuF"/>
|
||||||
|
<!--Unused field: IInterface$Inner.i-->
|
||||||
|
<!--Unused field: IInterface$Inner.k-->
|
||||||
|
</Match>
|
||||||
|
<Match class="InheritInner">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method InheritInner.main(String[]) At InheritInner.java:[line 15]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="InitialValues">
|
||||||
|
<BugCode name="UwF"/>
|
||||||
|
<!--Unwritten field: InitialValues.b-->
|
||||||
|
<!--Unwritten field: InitialValues.c-->
|
||||||
|
<!--Unwritten field: InitialValues.d-->
|
||||||
|
<!--Unwritten field: InitialValues.f-->
|
||||||
|
<!--Unwritten field: InitialValues.i-->
|
||||||
|
<!--Unwritten field: InitialValues.l-->
|
||||||
|
<!--Unwritten field: InitialValues.s-->
|
||||||
|
<!--Unwritten field: InitialValues.t-->
|
||||||
|
</Match>
|
||||||
|
<Match class="InnerRunnable1">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: InnerRunnable1.inner-->
|
||||||
|
</Match>
|
||||||
|
<Match class="InnerThread1">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: InnerThread1.inner-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Insect">
|
||||||
|
<BugCode name="UR"/>
|
||||||
|
<!--Uninitialized read of Insect.j in Insect.<init>() At Beetle.java:[line 9]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="InstantiateGenericType">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method InstantiateGenericType.main(String[]) At InstantiateGenericType.java:[line 19]-->
|
||||||
|
<!--Dead store to local variable in method InstantiateGenericType.main(String[]) At InstantiateGenericType.java:[line 23]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="JUnitDemo">
|
||||||
|
<BugCode name="IJU"/>
|
||||||
|
<!--TestCase JUnitDemo implements setUp but doesn't call super.setUp() At JUnitDemo.java:[lines 30-31]-->
|
||||||
|
<!--TestCase JUnitDemo implements tearDown but doesn't call super.tearDown() At JUnitDemo.java:[lines 36-37]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Joining">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Joining.main(String[]) At Joining.java:[line 47]-->
|
||||||
|
<!--Dead store to local variable in method Joining.main(String[]) At Joining.java:[line 48]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="LibTest">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method LibTest.main(String[]) At LibTest.java:[line 7]-->
|
||||||
|
<!--Dead store to local variable in method LibTest.main(String[]) At LibTest.java:[line 8]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Literals">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Literals.b-->
|
||||||
|
<!--Unread field: Literals.c-->
|
||||||
|
<!--Unread field: Literals.d1-->
|
||||||
|
<!--Unread field: Literals.d2-->
|
||||||
|
<!--Unread field: Literals.d3-->
|
||||||
|
<!--Unread field: Literals.f1-->
|
||||||
|
<!--Unread field: Literals.f2-->
|
||||||
|
<!--Unread field: Literals.f3-->
|
||||||
|
<!--Unread field: Literals.f4-->
|
||||||
|
<!--Unread field: Literals.f5-->
|
||||||
|
<!--Unread field: Literals.i1-->
|
||||||
|
<!--Unread field: Literals.i2-->
|
||||||
|
<!--Unread field: Literals.i3-->
|
||||||
|
<!--Unread field: Literals.n1-->
|
||||||
|
<!--Unread field: Literals.n2-->
|
||||||
|
<!--Unread field: Literals.n3-->
|
||||||
|
<!--Unread field: Literals.s-->
|
||||||
|
</Match>
|
||||||
|
<Match class="LockingMappedFiles">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--LockingMappedFiles.main(String[]) ignores return value of LockingMappedFiles$LockAndModify.<init>(java.nio.ByteBuffer,int,int) At LockingMappedFiles.java:[line 19]-->
|
||||||
|
<!--LockingMappedFiles.main(String[]) ignores return value of LockingMappedFiles$LockAndModify.<init>(java.nio.ByteBuffer,int,int) At LockingMappedFiles.java:[line 20]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Lunch">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Lunch.test() At Lunch.java:[line 30]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="MPair">
|
||||||
|
<BugCode name="HE"/>
|
||||||
|
<!--MPair defines equals and uses Object.hashCode()-->
|
||||||
|
</Match>
|
||||||
|
<Match class="MappedIO$4">
|
||||||
|
<BugCode name="OS"/>
|
||||||
|
<!--MappedIO$4.test() may fail to close stream At MappedIO.java:[line 61]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Mugs">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Mugs.c1-->
|
||||||
|
<!--Unread field: Mugs.c2-->
|
||||||
|
</Match>
|
||||||
|
<Match class="NIOInterruption">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method NIOInterruption.main(String[]) At NIOInterruption.java:[line 31]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel1">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Parcel1.ship(String) At Parcel1.java:[line 19]-->
|
||||||
|
<!--Dead store to local variable in method Parcel11.main(String[]) At Parcel11.java:[line 18]-->
|
||||||
|
<!--Dead store to local variable in method Parcel11.main(String[]) At Parcel11.java:[line 19]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel1$Contents">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel1$Contents be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel1$Destination">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel1$Destination be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel11">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method Parcel11.main(String[]) At Parcel11.java:[line 18]-->
|
||||||
|
<!--Dead store to local variable in method Parcel11.main(String[]) At Parcel11.java:[line 19]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel11$Contents">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel11$Contents be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel11$Destination">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel11$Destination be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel2$Contents">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel2$Contents be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel2$Destination">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel2$Destination be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel3$PContents">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel3$PContents be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel3$PDestination">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel3$PDestination be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel4$1PDestination">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel4$1PDestination be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Parcel5$1TrackingSlip">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should Parcel5$1TrackingSlip be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="PlaceSetting">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method PlaceSetting.main(String[]) At PlaceSetting.java:[line 66]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="PlaceSetting">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: PlaceSetting.frk-->
|
||||||
|
<!--Unread field: PlaceSetting.kn-->
|
||||||
|
<!--Unread field: PlaceSetting.pl-->
|
||||||
|
<!--Unread field: PlaceSetting.sp-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Pool">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Pool.classObject-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Poppet">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: Poppet.i-->
|
||||||
|
</Match>
|
||||||
|
<Match class="References">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method References.main(String[]) At References.java:[line 45]-->
|
||||||
|
<!--Dead store to local variable in method References.main(String[]) At References.java:[line 47]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ResponsiveUI">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--ResponsiveUI.main(String[]) ignores return value of ResponsiveUI.<init>() At ResponsiveUI.java:[line 27]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ResponsiveUI">
|
||||||
|
<BugCode name="SC"/>
|
||||||
|
<!--ResponsiveUI.<init>() invokes ResponsiveUI.start() At ResponsiveUI.java:[line 18]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="ReversibleArrayList$1$1">
|
||||||
|
<BugCode name="It"/>
|
||||||
|
<!--ReversibleArrayList$1$1.next() can't throw NoSuchElement exception At AdapterMethodIdiom.java:[line 14]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="RobotPool">
|
||||||
|
<BugCode name="Wa"/>
|
||||||
|
<!--Wait not in loop in RobotPool.hire(Class,Assembler) At CarBuilder.java:[line 168]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="SelfManaged">
|
||||||
|
<BugCode name="SC"/>
|
||||||
|
<!--SelfManaged.<init>() invokes java.lang.Thread.start() At SelfManaged.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="SimpleQueue">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--SimpleQueue.add(Object) ignores return value of java.util.LinkedList.offer(Object) At SimpleQueue.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="SimpleThread">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--SimpleThread.main(String[]) ignores return value of SimpleThread.<init>() At SimpleThread.java:[line 23]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="SimpleThread">
|
||||||
|
<BugCode name="SC"/>
|
||||||
|
<!--SimpleThread.<init>() invokes SimpleThread.start() At SimpleThread.java:[line 9]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="SprinklerSystem">
|
||||||
|
<BugCode name="UwF"/>
|
||||||
|
<!--Unwritten field: SprinklerSystem.f-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.i-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.source-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.valve1-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.valve2-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.valve3-->
|
||||||
|
<!--Unwritten field: SprinklerSystem.valve4-->
|
||||||
|
</Match>
|
||||||
|
<Match class="TellerManager">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--TellerManager.adjustTellerNumber() ignores return value of java.util.PriorityQueue.offer(Object) At BankTellerSimulation.java:[line 127]-->
|
||||||
|
<!--TellerManager.reassignOneTeller() ignores return value of java.util.Queue.offer(Object) At BankTellerSimulation.java:[line 150]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="TemperatureReading">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: TemperatureReading.time-->
|
||||||
|
</Match>
|
||||||
|
<Match class="URShift">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method URShift.main(String[]) At URShift.java:[line 8]-->
|
||||||
|
<!--Dead store to local variable in method URShift.main(String[]) At URShift.java:[line 10]-->
|
||||||
|
<!--Dead store to local variable in method URShift.main(String[]) At URShift.java:[line 12]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="UsingStringBuilder">
|
||||||
|
<BugCode name="MS"/>
|
||||||
|
<!--UsingStringBuilder.rand isn't final but should be-->
|
||||||
|
</Match>
|
||||||
|
<Match class="VeryBig">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: VeryBig.d-->
|
||||||
|
</Match>
|
||||||
|
<Match class="WaitPerson">
|
||||||
|
<BugCode name="UW"/>
|
||||||
|
<!--Unconditional wait in WaitPerson.run() At Restaurant.java:[line 22]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="WhitherStringBuilder">
|
||||||
|
<BugCode name="SBSC"/>
|
||||||
|
<!--Method WhitherStringBuilder.implicit(String[]) concatenates strings using + in a loop At WhitherStringBuilder.java:[line 7]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="WildcardRules">
|
||||||
|
<BugCode name="EC"/>
|
||||||
|
<!--Call to equals() comparing different types in WildcardRules.f(Holder) At WildcardRules.java:[line 11]-->
|
||||||
|
<!--Call to equals() comparing different types in WildcardRules.g(Holder) At WildcardRules.java:[line 17]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="Derived">
|
||||||
|
<BugCode name="EC"/>
|
||||||
|
</Match>
|
||||||
|
<Match class="WildcardRules">
|
||||||
|
<BugCode name="RV"/>
|
||||||
|
<!--WildcardRules.f(Holder) ignores return value of Holder.equals(Object) At WildcardRules.java:[line 11]-->
|
||||||
|
<!--WildcardRules.g(Holder) ignores return value of Holder.equals(Object) At WildcardRules.java:[line 17]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="annotations.database.Member">
|
||||||
|
<BugCode name="UwF"/>
|
||||||
|
<!--Unwritten field: annotations.database.Member.age-->
|
||||||
|
<!--Unwritten field: annotations.database.Member.firstName-->
|
||||||
|
<!--Unwritten field: annotations.database.Member.handle-->
|
||||||
|
<!--Unwritten field: annotations.database.Member.lastName-->
|
||||||
|
</Match>
|
||||||
|
<Match class="cloning.HorrorFlick">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method cloning.HorrorFlick.main(String[]) At HorrorFlick.java:[line 24]-->
|
||||||
|
<!--Dead store to local variable in method cloning.HorrorFlick.main(String[]) At HorrorFlick.java:[line 25]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="discovering.DocletTestClass">
|
||||||
|
<BugCode name="UuF"/>
|
||||||
|
<!--Unused field: discovering.DocletTestClass.BadCapitalizationField-->
|
||||||
|
<!--Unused field: discovering.DocletTestClass.i-->
|
||||||
|
<!--Unused field: discovering.DocletTestClass$BadInner.BadCapitalizationFieldInner-->
|
||||||
|
</Match>
|
||||||
|
<Match class="discovering.DocletTestClass$BadInner">
|
||||||
|
<BugCode name="UuF"/>
|
||||||
|
<!--Unused field: discovering.DocletTestClass$BadInner.BadCapitalizationFieldInner-->
|
||||||
|
</Match>
|
||||||
|
<Match class="discovering.DocletTestClass$BadInner$badCapitalizationClassInner">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should discovering.DocletTestClass$BadInner$badCapitalizationClassInner be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="discovering.DocletTestClass$Inner">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should discovering.DocletTestClass$Inner be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="discovering.DocletTestClass$badCapitalizationClass">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should discovering.DocletTestClass$badCapitalizationClass be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="holding.MapOfList">
|
||||||
|
<BugCode name="MS"/>
|
||||||
|
<!--holding.MapOfList.petPeople isn't final but should be-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.A$BImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.A$BImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.A$CImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.A$CImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.A$DImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.A$DImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.NestingInterfaces$BImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$BImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.NestingInterfaces$CImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$CImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.NestingInterfaces$EGImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$EGImp be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.NestingInterfaces$EImp">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$EImp be a _static_ inner class?-->
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$EImp2$EG be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="interfaces.nesting.NestingInterfaces$EImp2$EG">
|
||||||
|
<BugCode name="SIC"/>
|
||||||
|
<!--Should interfaces.nesting.NestingInterfaces$EImp2$EG be a _static_ inner class?-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.AUnit">
|
||||||
|
<BugCode name="SBSC"/>
|
||||||
|
<!--Method net.mindview.util.AUnit.main(String[]) concatenates strings using + in a loop At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.AbstractGenerator$Basic">
|
||||||
|
<BugCode name="It"/>
|
||||||
|
<!--net.mindview.util.AbstractGenerator$Basic.next() can't throw NoSuchElement exception At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.ClassNameFinder">
|
||||||
|
<BugCode name="DLS"/>
|
||||||
|
<!--Dead store to local variable in method net.mindview.util.ClassNameFinder.thisClass(byte[]) At <Unknown>:[line -1]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.ClassNameFinder">
|
||||||
|
<BugCode name="REC"/>
|
||||||
|
<!--Method net.mindview.util.ClassNameFinder.thisClass(byte[]) catches Exception, but Exception is not thrown in the try block and RuntimeException is not explicitly caught At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.Collections2">
|
||||||
|
<BugCode name="MS"/>
|
||||||
|
<!--net.mindview.util.Collections2.rsp isn't final but should be-->
|
||||||
|
<!--net.mindview.util.Collections2.simpleStrings isn't final but should be-->
|
||||||
|
<!--net.mindview.util.Collections2.geography isn't final but should be-->
|
||||||
|
<!--net.mindview.util.Collections2.countries isn't final but should be-->
|
||||||
|
<!--net.mindview.util.Collections2.capitals isn't final but should be-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.Collections2$StringGenerator">
|
||||||
|
<BugCode name="EI2"/>
|
||||||
|
<!--net.mindview.util.Collections2$StringGenerator.<init>(String[][],int) may expose internal representation by storing an externally mutable object into net.mindview.util.Collections2$StringGenerator.d At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.Collections2$StringPairGenerator">
|
||||||
|
<BugCode name="EI2"/>
|
||||||
|
<!--net.mindview.util.Collections2$StringPairGenerator.<init>(String[][]) may expose internal representation by storing an externally mutable object into net.mindview.util.Collections2$StringPairGenerator.d At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.CountryCapitals">
|
||||||
|
<BugCode name="MS"/>
|
||||||
|
<!--net.mindview.util.CountryCapitals.pairs is a mutable array-->
|
||||||
|
</Match>
|
||||||
|
<Match class="net.mindview.util.OSExecute">
|
||||||
|
<BugCode name="OS"/>
|
||||||
|
<!--net.mindview.util.OSExecute.command(String) may fail to close stream At <Unknown>:[line -1]-->
|
||||||
|
</Match>
|
||||||
|
<Match class="polymorphism.Sandwich">
|
||||||
|
<BugCode name="UrF"/>
|
||||||
|
<!--Unread field: polymorphism.Sandwich.b-->
|
||||||
|
<!--Unread field: polymorphism.Sandwich.c-->
|
||||||
|
<!--Unread field: polymorphism.Sandwich.l-->
|
||||||
|
</Match>
|
||||||
|
<Match class="polymorphism.music4.Instrument">
|
||||||
|
<BugCode name="UuF"/>
|
||||||
|
<!--Unused field: polymorphism.music4.Instrument.i-->
|
||||||
|
</Match>
|
||||||
|
<Match class="typeinfo.pets.ForNameCreator">
|
||||||
|
<BugCode name="EI"/>
|
||||||
|
<!--typeinfo.pets.ForNameCreator.getTypes() may expose internal representation by returning typeinfo.pets.ForNameCreator.types At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
<Match class="typeinfo.pets.LiteralPetCreator">
|
||||||
|
<BugCode name="EI"/>
|
||||||
|
<!--typeinfo.pets.LiteralPetCreator.getTypes() may expose internal representation by returning typeinfo.pets.LiteralPetCreator.types At unknown source line-->
|
||||||
|
</Match>
|
||||||
|
</FindBugsFilter>
|
||||||
31
JavaLint.py
Normal file
31
JavaLint.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
Runs javac -Xlint on all files in all subdirectories.
|
||||||
|
Collects results into JavaLint.txt
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
outputfile = "JavaLint.txt"
|
||||||
|
|
||||||
|
javadirs = []
|
||||||
|
for path, dirs, files in os.walk('.'):
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(".java"):
|
||||||
|
javadirs.append(path)
|
||||||
|
break
|
||||||
|
|
||||||
|
start = os.getcwd()
|
||||||
|
|
||||||
|
for jd in javadirs:
|
||||||
|
os.chdir(jd)
|
||||||
|
print jd
|
||||||
|
os.system("javac -source 1.5 -Xlint -Xlint:-serial *.java -Xstdout " + outputfile)
|
||||||
|
os.chdir(start)
|
||||||
|
|
||||||
|
results = open(start + os.sep + outputfile, 'w')
|
||||||
|
|
||||||
|
for jd in javadirs:
|
||||||
|
messages = open(jd + os.sep + outputfile).read()
|
||||||
|
if len(messages):
|
||||||
|
print >>results, '='*40 + "\n" + jd + "\n" + '='*40 + "\n" + messages
|
||||||
|
|
||||||
133
OutputGenerator.py
Normal file
133
OutputGenerator.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
Runs a Java program, appends output if it's not there
|
||||||
|
|
||||||
|
-force as first argument when doing batch files forces overwrite
|
||||||
|
|
||||||
|
"""
|
||||||
|
import os, re, sys
|
||||||
|
|
||||||
|
argTag = '// {Args: '
|
||||||
|
oldOutput = re.compile("/* Output:.*?\n(.*)\n\*///:~(?s)")
|
||||||
|
|
||||||
|
def makeOutputIncludedFile(path, fileName, changeReport, force = False):
|
||||||
|
oldDir = os.getcwd()
|
||||||
|
os.chdir(path)
|
||||||
|
base = fileName.split('.')[0]
|
||||||
|
package = ''
|
||||||
|
args = ''
|
||||||
|
command = None
|
||||||
|
for line in file(fileName):
|
||||||
|
if line.startswith("} /*"):
|
||||||
|
break # Out of for loop
|
||||||
|
if line.startswith("package"):
|
||||||
|
words = line.strip().split()
|
||||||
|
package = words[1][:-1] + '.' # remove ';'
|
||||||
|
if line.startswith(argTag):
|
||||||
|
args = line[len(argTag):].strip()
|
||||||
|
assert args.rfind('}') != -1, "%s, %s" % (args, fileName)
|
||||||
|
args = " " +args[:args.rfind('}')]
|
||||||
|
if line.startswith("// {main:"):
|
||||||
|
base = line.split()[-1]
|
||||||
|
base = base[:-1]
|
||||||
|
if line.startswith("// {Exec:"):
|
||||||
|
command = line.split(':', 1)[1].strip()[:-1]
|
||||||
|
if not command:
|
||||||
|
command = "java " + package + base + args
|
||||||
|
command += " > " + base + "-output.txt"
|
||||||
|
print command
|
||||||
|
result = os.system(command)
|
||||||
|
if(result != 0):
|
||||||
|
raise Exception, "Command returned nonzero value: " + str(result)
|
||||||
|
# Read output file that was just generated:
|
||||||
|
results = file(base + "-output.txt").read().strip()
|
||||||
|
# Strip off trailing spaces on each line:
|
||||||
|
results = "\n".join([line.rstrip() for line in results.split("\n")])
|
||||||
|
results = results.replace('\t', ' ')
|
||||||
|
if results:
|
||||||
|
if force or not oldOutput.findall(file(fileName).read()):
|
||||||
|
processedText = createProcessedJavaText(results, fileName)
|
||||||
|
open(fileName, 'w').write(processedText + "\n")
|
||||||
|
if changeReport:
|
||||||
|
changeReport.write(os.path.join(path, fileName) + "\n")
|
||||||
|
return # Don't need to try for error output
|
||||||
|
##### Duplicate for standard error output:
|
||||||
|
command += " 2> " + base + "-erroroutput.txt"
|
||||||
|
print command
|
||||||
|
result = os.system(command)
|
||||||
|
if(result != 0):
|
||||||
|
raise Exception, "Command returned nonzero value: " + str(result)
|
||||||
|
# Read error file that was just generated:
|
||||||
|
results = file(base + "-erroroutput.txt").read().strip()
|
||||||
|
# Strip off trailing spaces on each line:
|
||||||
|
results = "\n".join([line.rstrip() for line in results.split("\n")])
|
||||||
|
results = results.replace('\t', ' ')
|
||||||
|
if results:
|
||||||
|
if force or not oldOutput.findall(file(fileName).read()):
|
||||||
|
processedText = createProcessedJavaText(results, fileName)
|
||||||
|
open(fileName, 'w').write(processedText + "\n")
|
||||||
|
if changeReport:
|
||||||
|
changeReport.write(os.path.join(path, fileName) + "\n")
|
||||||
|
os.chdir(oldDir)
|
||||||
|
|
||||||
|
def createProcessedJavaText(results, fileName):
|
||||||
|
processedJava = ''
|
||||||
|
for line in [line.rstrip() for line in file(fileName)]:
|
||||||
|
if line.startswith("} ///:~"):
|
||||||
|
processedJava += "} /* Output:\n" + results + "\n*///:~"
|
||||||
|
return processedJava
|
||||||
|
if line.startswith("} /* Output:"):
|
||||||
|
processedJava += line + "\n" + results + "\n*///:~" # Preserve modifiers
|
||||||
|
return processedJava
|
||||||
|
processedJava += line + "\n"
|
||||||
|
raise Exception, "No marker found at end of file " + path + " " + fileName
|
||||||
|
|
||||||
|
class ReportFile:
|
||||||
|
def __init__(self, filePath):
|
||||||
|
self.filePath = filePath
|
||||||
|
self.file = None
|
||||||
|
def write(self, line):
|
||||||
|
if not self.file:
|
||||||
|
self.file = file(self.filePath, 'w')
|
||||||
|
self.file.write(line)
|
||||||
|
print line
|
||||||
|
def close(self):
|
||||||
|
if self.file:
|
||||||
|
self.file.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
start = os.getcwd()
|
||||||
|
args = sys.argv[1:]
|
||||||
|
forceFlag = False
|
||||||
|
if len(args):
|
||||||
|
if args[0] == "-force":
|
||||||
|
forceFlag = True
|
||||||
|
print "forceFlag = ", forceFlag
|
||||||
|
del args[0]
|
||||||
|
if len(args) > 0:
|
||||||
|
for javaSource in args:
|
||||||
|
if javaSource.endswith("."): javaSource = javaSource[:-1]
|
||||||
|
if not javaSource.endswith(".java"): javaSource += ".java"
|
||||||
|
os.system("javac " + javaSource)
|
||||||
|
makeOutputIncludedFile(os.getcwd(), javaSource, None, force = True)
|
||||||
|
else:
|
||||||
|
changeReport = ReportFile(os.path.join(start, "Changes.txt"))
|
||||||
|
for root, dirs, files in os.walk('.'):
|
||||||
|
if (os.sep + "gui") in root: continue
|
||||||
|
path = os.path.normpath(os.path.join(start,root))
|
||||||
|
print path
|
||||||
|
for name in [name for name in files if name.endswith(".java")]:
|
||||||
|
java = file(os.path.join(path, name)).read()
|
||||||
|
if "public static void main(String" in java and \
|
||||||
|
not "{RunByHand}" in java and \
|
||||||
|
not "{ThrowsException}" in java and \
|
||||||
|
not "/* (Execute to see output) *///:~" in java and \
|
||||||
|
not "} /* Same output as" in java:
|
||||||
|
if forceFlag or not "} /* Output:" in java:
|
||||||
|
print "\t", name
|
||||||
|
makeOutputIncludedFile(path, name, changeReport, force = forceFlag)
|
||||||
|
changeReport.close()
|
||||||
|
os.system("uedit32 /f Changes.txt &")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
200
OutputVerifier.py
Normal file
200
OutputVerifier.py
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
To do:
|
||||||
|
|
||||||
|
3) command-line argument (to test a single file)
|
||||||
|
|
||||||
|
- What about exceptions and aborts?
|
||||||
|
|
||||||
|
-If ...is embedded anywhere in a line, that portion becomes a .*? regexp
|
||||||
|
|
||||||
|
---------------
|
||||||
|
Find files with
|
||||||
|
/* Output:
|
||||||
|
|
||||||
|
Run the programs and capture the output, compare with anticipated output.
|
||||||
|
|
||||||
|
/* Output: (80% match)
|
||||||
|
|
||||||
|
For files that vary from run to run
|
||||||
|
|
||||||
|
Complete punt:
|
||||||
|
/* Output: (Sample)
|
||||||
|
|
||||||
|
(More elaborate design in SimpleTest1.py)
|
||||||
|
"""
|
||||||
|
import os, re, glob, sys, string, codecs
|
||||||
|
from difflib import SequenceMatcher
|
||||||
|
|
||||||
|
argTag = '// {Args: '
|
||||||
|
targetOutput = re.compile("/* Output:(.*?)\n(.*)\n\*///:~", re.DOTALL)
|
||||||
|
|
||||||
|
class SimpleTest:
|
||||||
|
|
||||||
|
def __init__(self, fileName, text, referencePath, reportFile):
|
||||||
|
self.fileName = fileName
|
||||||
|
self.normalOutput = self.fileName + "-output.txt"
|
||||||
|
self.errorOutput = self.fileName + "-erroroutput.txt"
|
||||||
|
self.text = text
|
||||||
|
self.referencePath = referencePath
|
||||||
|
self.reportFile = reportFile
|
||||||
|
self.package = ""
|
||||||
|
self.args = ""
|
||||||
|
self.runTest = True
|
||||||
|
self.insertOutput = True
|
||||||
|
self.EmbeddedComparisonOutput = False
|
||||||
|
self.comparisonFile = None
|
||||||
|
self.lines = self.text.split("\n")
|
||||||
|
for line in self.lines:
|
||||||
|
if "{RunByHand}" in line or \
|
||||||
|
line.startswith("import javax.swing.*;") or \
|
||||||
|
"c12:ZipCompress.java" in line or \
|
||||||
|
"/* (Execute to see output) *///:~" in line:
|
||||||
|
self.runTest = False
|
||||||
|
if line.startswith("package"):
|
||||||
|
self.package = line.split()[1][:-1] + "."
|
||||||
|
if line.startswith(argTag):
|
||||||
|
self.args = line[len(argTag):].strip()
|
||||||
|
assert self.args.rfind('}') != -1, "%s, %s" % (self.args, referencePath)
|
||||||
|
self.args = self.args[:self.args.rfind('}')]
|
||||||
|
if line.startswith("// {main:"):
|
||||||
|
self.fileName = line.split()[-1][:-1]
|
||||||
|
if line.startswith("// {Exec:"):
|
||||||
|
self.command = line.split(':', 1)[1].strip()[:-1]
|
||||||
|
if "/* Output:" in line:
|
||||||
|
self.EmbeddedComparisonOutput = True
|
||||||
|
if line.startswith("} /*"):
|
||||||
|
break # Out of for loop
|
||||||
|
#if "} ///:~" in line: # Extra space
|
||||||
|
# self.insertOutput = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not self.runTest: return
|
||||||
|
if not hasattr(self, "command"):
|
||||||
|
self.command = "java " + self.package + self.fileName + " " + self.args
|
||||||
|
# Capture standard output into a local file.
|
||||||
|
self.command = self.command + " > " + self.normalOutput
|
||||||
|
print self.command
|
||||||
|
os.system(self.command)
|
||||||
|
if os.stat(self.normalOutput).st_size:
|
||||||
|
return self.compareResults(self.normalOutput)
|
||||||
|
# Capture error output into a local file.
|
||||||
|
# The '2>' requires cygwin under Windows, or *nix:
|
||||||
|
self.command = self.command + " 2> " + self.errorOutput
|
||||||
|
print self.command
|
||||||
|
os.system(self.command)
|
||||||
|
return self.compareResults(self.errorOutput)
|
||||||
|
|
||||||
|
def compareResults(self, fileName):
|
||||||
|
# Read output file that was just generated:
|
||||||
|
results = makePrintable(file(fileName).read())
|
||||||
|
results = results.replace('\t', ' ')
|
||||||
|
results = results.strip()
|
||||||
|
file("Generated.txt",'w').write(results)
|
||||||
|
# Strip off trailing spaces on each line:
|
||||||
|
results = "\n".join([line.rstrip() for line in results.split("\n")])
|
||||||
|
controlSample = self.getControlSample()
|
||||||
|
ratio = 1.0
|
||||||
|
if controlSample:
|
||||||
|
controlOutput = controlSample.group(2).rstrip()
|
||||||
|
if "\n..." in controlOutput:
|
||||||
|
controlLines = controlOutput.split("\n")[:-1]
|
||||||
|
resultLines = results.split("\n")[:len(controlLines)]
|
||||||
|
controlOutput = "\n".join(controlLines)
|
||||||
|
results = "\n".join(resultLines)
|
||||||
|
file("controlOutput.txt",'w').write(controlOutput)
|
||||||
|
modifier = controlSample.group(1)
|
||||||
|
if "match" in modifier:
|
||||||
|
ratio = float(re.findall("\d+", modifier)[0]) / 100
|
||||||
|
print "Looking for", ratio, "match"
|
||||||
|
if "Sample" in modifier:
|
||||||
|
ratio = 0.0
|
||||||
|
actualRatio = SequenceMatcher(None, controlOutput, results).ratio()
|
||||||
|
if actualRatio < ratio:
|
||||||
|
self.reportFile.write("mismatch in " + self.referencePath + "\n")
|
||||||
|
self.reportFile.write("Actual ratio " + str(actualRatio) + "\n")
|
||||||
|
self.reportFile.write("expected:\n")
|
||||||
|
self.reportFile.write(controlOutput + "\n")
|
||||||
|
self.reportFile.write("----------actual:----------\n")
|
||||||
|
self.reportFile.write(results + "\n")
|
||||||
|
file(self.fileName + "-control.txt", 'w').write(controlOutput)
|
||||||
|
file(self.fileName + "-results.txt", 'w').write(results)
|
||||||
|
self.reportFile.write("---------------------------\n")
|
||||||
|
os.system("cmp " + self.fileName + "-control.txt "
|
||||||
|
+ self.fileName + "-results.txt"
|
||||||
|
+ " > cmp-out.txt")
|
||||||
|
self.reportFile.write(file("cmp-out.txt").read())
|
||||||
|
self.reportFile.write("=" * 40 + "\n")
|
||||||
|
|
||||||
|
else:
|
||||||
|
pass #!!! No control sample, create initial one here
|
||||||
|
|
||||||
|
def appendOutput(self):
|
||||||
|
if self.insertOutput:
|
||||||
|
# Rewrite the tail of the source file if the result is nonzero
|
||||||
|
self.lines[-2] = '}'
|
||||||
|
self.lines[-1] = "/* Output:"
|
||||||
|
for tline in file(self.fileName + "-output.txt"):
|
||||||
|
self.lines.append(tline.rstrip())
|
||||||
|
self.lines.append("*///:~")
|
||||||
|
self.lines.append("")
|
||||||
|
file(self.fileName + ".java", 'w').write("\n".join(self.lines))
|
||||||
|
|
||||||
|
def getControlSample(self):
|
||||||
|
"""Finds the control sample, returns an re group
|
||||||
|
First element is the arguments, second is the actual data"""
|
||||||
|
if self.EmbeddedComparisonOutput:
|
||||||
|
self.sourceOutput = targetOutput.search(self.text)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
return self.sourceOutput
|
||||||
|
|
||||||
|
def makePrintable(s):
|
||||||
|
for c in s:
|
||||||
|
if c not in string.printable: return _makePrintable(s)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def _makePrintable(s):
|
||||||
|
result = ''
|
||||||
|
for c in s:
|
||||||
|
if c not in string.printable: result += ' '
|
||||||
|
else: result += c
|
||||||
|
return result
|
||||||
|
|
||||||
|
class ReportFile:
|
||||||
|
def __init__(self, filePath):
|
||||||
|
self.filePath = filePath
|
||||||
|
self.file = None
|
||||||
|
def write(self, line):
|
||||||
|
if not self.file:
|
||||||
|
self.file = file(self.filePath, 'w')
|
||||||
|
self.file.write(line)
|
||||||
|
print line
|
||||||
|
def close(self):
|
||||||
|
if self.file:
|
||||||
|
self.file.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
javaSource = sys.argv[1]
|
||||||
|
if javaSource.endswith("."): javaSource = javaSource[:-1]
|
||||||
|
if not javaSource.endswith(".java"): javaSource += ".java"
|
||||||
|
os.system("javac " + javaSource)
|
||||||
|
SimpleTest(javaSource.split('.')[0], file(javaSource).read(), javaSource, sys.stdout).run()
|
||||||
|
sys.exit()
|
||||||
|
start = os.getcwd()
|
||||||
|
reportFile = ReportFile(start + os.sep + "OutputErrors.txt")
|
||||||
|
for root, dirs, files in os.walk('.'):
|
||||||
|
print root
|
||||||
|
os.chdir(root)
|
||||||
|
for f in [name.split('.')[0] for name in files if name.endswith(".java")]:
|
||||||
|
text = file(f + ".java").read()
|
||||||
|
# Only perform verification if there is an output tag:
|
||||||
|
if text.find("/* Output:") != -1:
|
||||||
|
referencePath = os.path.join(root, f + ".java")
|
||||||
|
SimpleTest(f, text, referencePath, reportFile).run()
|
||||||
|
os.chdir(start)
|
||||||
|
reportFile.close()
|
||||||
|
if reportFile.file:
|
||||||
|
print "Errors in OutputErrors.txt"
|
||||||
|
|
||||||
54
RedundantImportDetector.py
Normal file
54
RedundantImportDetector.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
"""RedundantImportDetector.py
|
||||||
|
Discover redundant java imports using brute force.
|
||||||
|
Requires Python 2.3"""
|
||||||
|
import os, sys, re
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
|
reportFile = file("RedundantImports.txt", 'w')
|
||||||
|
|
||||||
|
startDir = 'D:\\aaa-TIJ4\\code'
|
||||||
|
|
||||||
|
# Regular expression to find the block of import statements:
|
||||||
|
findImports = re.compile("\n(?:import .*?\n)+")
|
||||||
|
|
||||||
|
baseDir = os.path.abspath(".")
|
||||||
|
|
||||||
|
print "basDir:", baseDir
|
||||||
|
|
||||||
|
def main():
|
||||||
|
for javaFile in glob("*.java") + glob("**/*.java"):
|
||||||
|
print javaFile
|
||||||
|
checkImports(os.path.join(baseDir, javaFile))
|
||||||
|
|
||||||
|
def checkImports(javaFile):
|
||||||
|
java = file(javaFile).read()
|
||||||
|
imports = findImports.search(java)
|
||||||
|
if imports:
|
||||||
|
imports = [f for f in imports.group(0).split('\n') if f != '']
|
||||||
|
fileParts = findImports.split(java)
|
||||||
|
assert len(fileParts) == 2
|
||||||
|
for mutated in mutateImports(imports):
|
||||||
|
file(javaFile, 'w').write(fileParts[0] + mutated + fileParts[1])
|
||||||
|
print "changing to", os.path.dirname(javaFile)
|
||||||
|
os.chdir(os.path.dirname(javaFile))
|
||||||
|
if os.system("javac " + os.path.basename(javaFile)) == 0:
|
||||||
|
print >>reportFile, javaFile + "\n" + mutated
|
||||||
|
redundantRemoved = "\n".join(
|
||||||
|
[m for m in mutated.split("\n")
|
||||||
|
if not m.startswith("//")])
|
||||||
|
print >>reportFile, redundantRemoved
|
||||||
|
file(javaFile, 'w').write(fileParts[0] +
|
||||||
|
redundantRemoved + fileParts[1])
|
||||||
|
return # No further attempts
|
||||||
|
file(javaFile, 'w').write(java) # Restore original file
|
||||||
|
|
||||||
|
def mutateImports(imports):
|
||||||
|
'''Generates different versions of imports, each with a
|
||||||
|
different line commented out'''
|
||||||
|
for i in range(len(imports)):
|
||||||
|
mutated = imports[:]
|
||||||
|
mutated[i] = '//' + mutated[i]
|
||||||
|
yield "\n".join([''] + mutated + [''])
|
||||||
|
|
||||||
|
if __name__ == "__main__": main()
|
||||||
|
|
||||||
128
build.xml
Normal file
128
build.xml
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<project basedir="." default="run" name="Thinking in Java, 4th Edition by Bruce Eckel">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Main build.xml for the source code for
|
||||||
|
Thinking in Java, 4th Edition by Bruce Eckel
|
||||||
|
Code available at http://www.MindView.net
|
||||||
|
See copyright notice in CopyRight.txt
|
||||||
|
|
||||||
|
Ant available from: http://jakarta.apache.org/ant
|
||||||
|
|
||||||
|
To see options, type: ant -p
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<condition property="version1.5">
|
||||||
|
<equals arg1="1.5" arg2="${ant.java.version}"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<filelist id="buildfiles" dir="."
|
||||||
|
files="object/build.xml
|
||||||
|
operators/build.xml
|
||||||
|
control/build.xml
|
||||||
|
initialization/build.xml
|
||||||
|
access/build.xml
|
||||||
|
net/build.xml
|
||||||
|
reusing/build.xml
|
||||||
|
polymorphism/build.xml
|
||||||
|
interfaces/build.xml
|
||||||
|
innerclasses/build.xml
|
||||||
|
holding/build.xml
|
||||||
|
exceptions/build.xml
|
||||||
|
strings/build.xml
|
||||||
|
typeinfo/build.xml
|
||||||
|
generics/build.xml
|
||||||
|
arrays/build.xml
|
||||||
|
containers/build.xml
|
||||||
|
io/build.xml
|
||||||
|
xml/build.xml
|
||||||
|
enumerated/build.xml
|
||||||
|
annotations/build.xml
|
||||||
|
concurrency/build.xml
|
||||||
|
gui/build.xml
|
||||||
|
frogbean/build.xml
|
||||||
|
bangbean/build.xml
|
||||||
|
swt/build.xml
|
||||||
|
"/>
|
||||||
|
|
||||||
|
<target name="run" description="Compiles and runs all examples">
|
||||||
|
<delete file="errors.txt"/>
|
||||||
|
<subant>
|
||||||
|
<filelist refid="buildfiles"/>
|
||||||
|
</subant>
|
||||||
|
<available file="errors.txt" property="errors"/>
|
||||||
|
<antcall target="finish"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="build" description="Compiles all examples">
|
||||||
|
<fail message="J2SE5 required" unless="version1.5"/>
|
||||||
|
<delete file="errors.txt"/>
|
||||||
|
<subant target="build">
|
||||||
|
<filelist refid="buildfiles"/>
|
||||||
|
</subant>
|
||||||
|
<available file="errors.txt" property="errors"/>
|
||||||
|
<antcall target="finish"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="clean" description="delete all byproducts">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/*Output.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/log.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="errors.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="failures"/>
|
||||||
|
</delete>
|
||||||
|
<echo message="clean successful"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="finish" if="errors">
|
||||||
|
<echo message="Errors occurred. See errors.txt for information."/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="verify" depends="run"
|
||||||
|
description="Verifies comment output; requires Python 2.3">
|
||||||
|
<exec executable="python">
|
||||||
|
<arg value="OutputVerifier.py"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="findbugs" depends="build"
|
||||||
|
description="Runs findbugs. Must install findbugs from findbugs.sourceforge.net">
|
||||||
|
<exec executable="findbugs.bat">
|
||||||
|
<arg value="-textui"/>
|
||||||
|
<arg value="-sortByClass"/>
|
||||||
|
<arg value="-exclude"/>
|
||||||
|
<arg value="FindBugsFilter.xml"/>
|
||||||
|
<arg value="-html"/>
|
||||||
|
<arg value="."/>
|
||||||
|
<redirector output="findbugs.html"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="findbugs-plain" depends="build"
|
||||||
|
description="Runs findbugs with plain text output">
|
||||||
|
<exec executable="findbugs.bat">
|
||||||
|
<arg value="-textui"/>
|
||||||
|
<arg value="-sortByClass"/>
|
||||||
|
<arg value="-exclude"/>
|
||||||
|
<arg value="FindBugsFilter.xml"/>
|
||||||
|
<arg value="."/>
|
||||||
|
<redirector output="findbugs.txt"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="findbugs-xml" depends="build"
|
||||||
|
description="Runs findbugs with xml output">
|
||||||
|
<exec executable="findbugs.bat">
|
||||||
|
<arg value="-textui"/>
|
||||||
|
<arg value="-sortByClass"/>
|
||||||
|
<arg value="-exclude"/>
|
||||||
|
<arg value="FindBugsFilter.xml"/>
|
||||||
|
<arg value="-xml"/>
|
||||||
|
<arg value="."/>
|
||||||
|
<redirector output="findbugs.xml"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
28
chapterOrder.xml
Normal file
28
chapterOrder.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<filelist id="buildfiles" dir="."
|
||||||
|
files="object/build.xml
|
||||||
|
operators/build.xml
|
||||||
|
control/build.xml
|
||||||
|
initialization/build.xml
|
||||||
|
access/build.xml
|
||||||
|
net/build.xml
|
||||||
|
reusing/build.xml
|
||||||
|
polymorphism/build.xml
|
||||||
|
interfaces/build.xml
|
||||||
|
innerclasses/build.xml
|
||||||
|
holding/build.xml
|
||||||
|
exceptions/build.xml
|
||||||
|
strings/build.xml
|
||||||
|
typeinfo/build.xml
|
||||||
|
generics/build.xml
|
||||||
|
arrays/build.xml
|
||||||
|
containers/build.xml
|
||||||
|
io/build.xml
|
||||||
|
xml/build.xml
|
||||||
|
enumerated/build.xml
|
||||||
|
annotations/build.xml
|
||||||
|
concurrency/build.xml
|
||||||
|
gui/build.xml
|
||||||
|
frogbean/build.xml
|
||||||
|
bangbean/build.xml
|
||||||
|
swt/build.xml
|
||||||
|
"/>
|
||||||
11
src/access/Cake.java
Normal file
11
src/access/Cake.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package access;//: access/Cake.java
|
||||||
|
// Accesses a class in a separate compilation unit.
|
||||||
|
|
||||||
|
class Cake {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Pie x = new Pie();
|
||||||
|
x.f();
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Pie.f()
|
||||||
|
*///:~
|
||||||
19
src/access/ChocolateChip.java
Normal file
19
src/access/ChocolateChip.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package access;//: access/ChocolateChip.java
|
||||||
|
// Can't use package-access member from another package.
|
||||||
|
import access.dessert.*;
|
||||||
|
|
||||||
|
public class ChocolateChip extends Cookie {
|
||||||
|
public ChocolateChip() {
|
||||||
|
System.out.println("ChocolateChip constructor");
|
||||||
|
}
|
||||||
|
public void chomp() {
|
||||||
|
//! bite(); // Can't access bite
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ChocolateChip x = new ChocolateChip();
|
||||||
|
x.chomp();
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Cookie constructor
|
||||||
|
ChocolateChip constructor
|
||||||
|
*///:~
|
||||||
17
src/access/ChocolateChip2.java
Normal file
17
src/access/ChocolateChip2.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package access;//: access/ChocolateChip2.java
|
||||||
|
import access.cookie2.*;
|
||||||
|
|
||||||
|
public class ChocolateChip2 extends Cookie {
|
||||||
|
public ChocolateChip2() {
|
||||||
|
System.out.println("ChocolateChip2 constructor");
|
||||||
|
}
|
||||||
|
public void chomp() { bite(); } // Protected method
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ChocolateChip2 x = new ChocolateChip2();
|
||||||
|
x.chomp();
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Cookie constructor
|
||||||
|
ChocolateChip2 constructor
|
||||||
|
bite
|
||||||
|
*///:~
|
||||||
12
src/access/Dinner.java
Normal file
12
src/access/Dinner.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package access;//: access/Dinner.java
|
||||||
|
// Uses the library.
|
||||||
|
import access.dessert.*;
|
||||||
|
|
||||||
|
public class Dinner {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Cookie x = new Cookie();
|
||||||
|
//! x.bite(); // Can't access
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Cookie constructor
|
||||||
|
*///:~
|
||||||
7
src/access/FullQualification.java
Normal file
7
src/access/FullQualification.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package access;//: access/FullQualification.java
|
||||||
|
|
||||||
|
public class FullQualification {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
java.util.ArrayList list = new java.util.ArrayList();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
16
src/access/IceCream.java
Normal file
16
src/access/IceCream.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package access;//: access/IceCream.java
|
||||||
|
// Demonstrates "private" keyword.
|
||||||
|
|
||||||
|
class Sundae {
|
||||||
|
private Sundae() {}
|
||||||
|
static Sundae makeASundae() {
|
||||||
|
return new Sundae();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IceCream {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//! Sundae x = new Sundae();
|
||||||
|
Sundae x = Sundae.makeASundae();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
8
src/access/ImportedMyClass.java
Normal file
8
src/access/ImportedMyClass.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package access;//: access/ImportedMyClass.java
|
||||||
|
import access.mypackage.*;
|
||||||
|
|
||||||
|
public class ImportedMyClass {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
MyClass m = new MyClass();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
13
src/access/LibTest.java
Normal file
13
src/access/LibTest.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package access;//: access/LibTest.java
|
||||||
|
// Uses the library.
|
||||||
|
import net.mindview.simple.*;
|
||||||
|
|
||||||
|
public class LibTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Vector v = new Vector();
|
||||||
|
List l = new List();
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
net.mindview.simple.Vector
|
||||||
|
net.mindview.simple.List
|
||||||
|
*///:~
|
||||||
36
src/access/Lunch.java
Normal file
36
src/access/Lunch.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package access;//: access/Lunch.java
|
||||||
|
// Demonstrates class access specifiers. Make a class
|
||||||
|
// effectively private with private constructors:
|
||||||
|
|
||||||
|
class Soup1 {
|
||||||
|
private Soup1() {}
|
||||||
|
// (1) Allow creation via static method:
|
||||||
|
public static Soup1 makeSoup() {
|
||||||
|
return new Soup1();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Soup2 {
|
||||||
|
private Soup2() {}
|
||||||
|
// (2) Create a static object and return a reference
|
||||||
|
// upon request.(The "Singleton" pattern):
|
||||||
|
private static Soup2 ps1 = new Soup2();
|
||||||
|
public static Soup2 access() {
|
||||||
|
return ps1;
|
||||||
|
}
|
||||||
|
public void f() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only one public class allowed per file:
|
||||||
|
public class Lunch {
|
||||||
|
void testPrivate() {
|
||||||
|
// Can't do this! Private constructor:
|
||||||
|
//! Soup1 soup = new Soup1();
|
||||||
|
}
|
||||||
|
void testStatic() {
|
||||||
|
Soup1 soup = Soup1.makeSoup();
|
||||||
|
}
|
||||||
|
void testSingleton() {
|
||||||
|
Soup2.access().f();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
12
src/access/OrganizedByAccess.java
Normal file
12
src/access/OrganizedByAccess.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package access;//: access/OrganizedByAccess.java
|
||||||
|
|
||||||
|
public class OrganizedByAccess {
|
||||||
|
public void pub1() { /* ... */ }
|
||||||
|
public void pub2() { /* ... */ }
|
||||||
|
public void pub3() { /* ... */ }
|
||||||
|
private void priv1() { /* ... */ }
|
||||||
|
private void priv2() { /* ... */ }
|
||||||
|
private void priv3() { /* ... */ }
|
||||||
|
private int i;
|
||||||
|
// ...
|
||||||
|
} ///:~
|
||||||
6
src/access/Pie.java
Normal file
6
src/access/Pie.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package access;//: access/Pie.java
|
||||||
|
// The other class.
|
||||||
|
|
||||||
|
class Pie {
|
||||||
|
void f() { System.out.println("Pie.f()"); }
|
||||||
|
} ///:~
|
||||||
17
src/access/PrintTest.java
Normal file
17
src/access/PrintTest.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package access;//: access/PrintTest.java
|
||||||
|
// Uses the static printing methods in Print.java.
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class PrintTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
print("Available from now on!");
|
||||||
|
print(100);
|
||||||
|
print(100L);
|
||||||
|
print(3.14159);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Available from now on!
|
||||||
|
100
|
||||||
|
100
|
||||||
|
3.14159
|
||||||
|
*///:~
|
||||||
8
src/access/QualifiedMyClass.java
Normal file
8
src/access/QualifiedMyClass.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package access;//: access/QualifiedMyClass.java
|
||||||
|
|
||||||
|
public class QualifiedMyClass {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
access.mypackage.MyClass m =
|
||||||
|
new access.mypackage.MyClass();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
8
src/access/SingleImport.java
Normal file
8
src/access/SingleImport.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package access;//: access/SingleImport.java
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class SingleImport {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ArrayList list = new java.util.ArrayList();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
189
src/access/build.xml
Normal file
189
src/access/build.xml
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<project
|
||||||
|
basedir="."
|
||||||
|
default="run"
|
||||||
|
name="Thinking in Java, 4th Edition by Bruce Eckel (chapter: access)">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
build.xml for the source code for the access chapter of
|
||||||
|
Thinking in Java, 4th Edition by Bruce Eckel
|
||||||
|
Source code available at http://www.MindView.net
|
||||||
|
See copyright notice in CopyRight.txt
|
||||||
|
|
||||||
|
Ant available from: http://jakarta.apache.org/ant
|
||||||
|
|
||||||
|
To see options, type: ant -p
|
||||||
|
|
||||||
|
This file was automatically generated by AntBuilder
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<condition property="version1.5">
|
||||||
|
<equals arg1="1.5" arg2="${ant.java.version}"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<target name="net_mindview_util">
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
srcdir="${basedir}/../net/mindview/util/">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="net_mindview_simple">
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
srcdir="${basedir}/../net/mindview/simple/">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="net_mindview_util,net_mindview_simple"
|
||||||
|
description="Build all classes in this directory"
|
||||||
|
name="build">
|
||||||
|
<fail message="J2SE5 required" unless="version1.5"/>
|
||||||
|
<echo message="Building 'access'"/>
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
debug="true"
|
||||||
|
srcdir="${basedir}">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
<echo message="Build 'access' succeeded"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="Cake">
|
||||||
|
<java
|
||||||
|
classname="Cake"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ChocolateChip">
|
||||||
|
<java
|
||||||
|
classname="ChocolateChip"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ChocolateChip2">
|
||||||
|
<java
|
||||||
|
classname="ChocolateChip2"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="Dinner">
|
||||||
|
<java
|
||||||
|
classname="Dinner"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="FullQualification">
|
||||||
|
<java
|
||||||
|
classname="FullQualification"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="IceCream">
|
||||||
|
<java
|
||||||
|
classname="IceCream"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ImportedMyClass">
|
||||||
|
<java
|
||||||
|
classname="ImportedMyClass"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="LibTest">
|
||||||
|
<java
|
||||||
|
classname="LibTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="PrintTest">
|
||||||
|
<java
|
||||||
|
classname="PrintTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="QualifiedMyClass">
|
||||||
|
<java
|
||||||
|
classname="QualifiedMyClass"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="SingleImport">
|
||||||
|
<java
|
||||||
|
classname="SingleImport"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../access/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="build"
|
||||||
|
description="Compile and run"
|
||||||
|
name="run">
|
||||||
|
<touch file="failures"/>
|
||||||
|
<antcall target="Cake"/>
|
||||||
|
<antcall target="ChocolateChip"/>
|
||||||
|
<antcall target="ChocolateChip2"/>
|
||||||
|
<antcall target="Dinner"/>
|
||||||
|
<antcall target="FullQualification"/>
|
||||||
|
<antcall target="IceCream"/>
|
||||||
|
<antcall target="ImportedMyClass"/>
|
||||||
|
<antcall target="LibTest"/>
|
||||||
|
<antcall target="PrintTest"/>
|
||||||
|
<antcall target="QualifiedMyClass"/>
|
||||||
|
<antcall target="SingleImport"/>
|
||||||
|
<delete file="failures"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target description="delete all byproducts" name="clean">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/*Output.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/log.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="failures"/>
|
||||||
|
</delete>
|
||||||
|
<echo message="clean successful"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
||||||
|
|
||||||
11
src/access/cookie2/Cookie.java
Normal file
11
src/access/cookie2/Cookie.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//: access/cookie2/Cookie.java
|
||||||
|
package access.cookie2;
|
||||||
|
|
||||||
|
public class Cookie {
|
||||||
|
public Cookie() {
|
||||||
|
System.out.println("Cookie constructor");
|
||||||
|
}
|
||||||
|
protected void bite() {
|
||||||
|
System.out.println("bite");
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
10
src/access/dessert/Cookie.java
Normal file
10
src/access/dessert/Cookie.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//: access/dessert/Cookie.java
|
||||||
|
// Creates a library.
|
||||||
|
package access.dessert;
|
||||||
|
|
||||||
|
public class Cookie {
|
||||||
|
public Cookie() {
|
||||||
|
System.out.println("Cookie constructor");
|
||||||
|
}
|
||||||
|
void bite() { System.out.println("bite"); }
|
||||||
|
} ///:~
|
||||||
6
src/access/mypackage/MyClass.java
Normal file
6
src/access/mypackage/MyClass.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//: access/mypackage/MyClass.java
|
||||||
|
package access.mypackage;
|
||||||
|
|
||||||
|
public class MyClass {
|
||||||
|
// ...
|
||||||
|
} ///:~
|
||||||
26
src/annotations/AtUnitComposition.java
Normal file
26
src/annotations/AtUnitComposition.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//: annotations/AtUnitComposition.java
|
||||||
|
// Creating non-embedded tests.
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitComposition {
|
||||||
|
AtUnitExample1 testObject = new AtUnitExample1();
|
||||||
|
@Test boolean _methodOne() {
|
||||||
|
return
|
||||||
|
testObject.methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
@Test boolean _methodTwo() {
|
||||||
|
return testObject.methodTwo() == 2;
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitComposition");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitComposition
|
||||||
|
. _methodOne
|
||||||
|
. _methodTwo This is methodTwo
|
||||||
|
|
||||||
|
OK (2 tests)
|
||||||
|
*///:~
|
||||||
39
src/annotations/AtUnitExample1.java
Normal file
39
src/annotations/AtUnitExample1.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//: annotations/AtUnitExample1.java
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitExample1 {
|
||||||
|
public String methodOne() {
|
||||||
|
return "This is methodOne";
|
||||||
|
}
|
||||||
|
public int methodTwo() {
|
||||||
|
System.out.println("This is methodTwo");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
@Test boolean methodOneTest() {
|
||||||
|
return methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
@Test boolean m2() { return methodTwo() == 2; }
|
||||||
|
@Test private boolean m3() { return true; }
|
||||||
|
// Shows output for failure:
|
||||||
|
@Test boolean failureTest() { return false; }
|
||||||
|
@Test boolean anotherDisappointment() { return false; }
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExample1");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitExample1
|
||||||
|
. methodOneTest
|
||||||
|
. m2 This is methodTwo
|
||||||
|
|
||||||
|
. m3
|
||||||
|
. failureTest (failed)
|
||||||
|
. anotherDisappointment (failed)
|
||||||
|
(5 tests)
|
||||||
|
|
||||||
|
>>> 2 FAILURES <<<
|
||||||
|
annotations.AtUnitExample1: failureTest
|
||||||
|
annotations.AtUnitExample1: anotherDisappointment
|
||||||
|
*///:~
|
||||||
48
src/annotations/AtUnitExample2.java
Normal file
48
src/annotations/AtUnitExample2.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//: annotations/AtUnitExample2.java
|
||||||
|
// Assertions and exceptions can be used in @Tests.
|
||||||
|
package annotations;
|
||||||
|
import java.io.*;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitExample2 {
|
||||||
|
public String methodOne() {
|
||||||
|
return "This is methodOne";
|
||||||
|
}
|
||||||
|
public int methodTwo() {
|
||||||
|
System.out.println("This is methodTwo");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
@Test void assertExample() {
|
||||||
|
assert methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
@Test void assertFailureExample() {
|
||||||
|
assert 1 == 2: "What a surprise!";
|
||||||
|
}
|
||||||
|
@Test void exceptionExample() throws IOException {
|
||||||
|
new FileInputStream("nofile.txt"); // Throws
|
||||||
|
}
|
||||||
|
@Test boolean assertAndReturn() {
|
||||||
|
// Assertion with message:
|
||||||
|
assert methodTwo() == 2: "methodTwo must equal 2";
|
||||||
|
return methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExample2");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitExample2
|
||||||
|
. assertExample
|
||||||
|
. assertFailureExample java.lang.AssertionError: What a surprise!
|
||||||
|
(failed)
|
||||||
|
. exceptionExample java.io.FileNotFoundException: nofile.txt (The system cannot find the file specified)
|
||||||
|
(failed)
|
||||||
|
. assertAndReturn This is methodTwo
|
||||||
|
|
||||||
|
(4 tests)
|
||||||
|
|
||||||
|
>>> 2 FAILURES <<<
|
||||||
|
annotations.AtUnitExample2: assertFailureExample
|
||||||
|
annotations.AtUnitExample2: exceptionExample
|
||||||
|
*///:~
|
||||||
36
src/annotations/AtUnitExample3.java
Normal file
36
src/annotations/AtUnitExample3.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//: annotations/AtUnitExample3.java
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitExample3 {
|
||||||
|
private int n;
|
||||||
|
public AtUnitExample3(int n) { this.n = n; }
|
||||||
|
public int getN() { return n; }
|
||||||
|
public String methodOne() {
|
||||||
|
return "This is methodOne";
|
||||||
|
}
|
||||||
|
public int methodTwo() {
|
||||||
|
System.out.println("This is methodTwo");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
@TestObjectCreate static AtUnitExample3 create() {
|
||||||
|
return new AtUnitExample3(47);
|
||||||
|
}
|
||||||
|
@Test boolean initialization() { return n == 47; }
|
||||||
|
@Test boolean methodOneTest() {
|
||||||
|
return methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
@Test boolean m2() { return methodTwo() == 2; }
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExample3");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitExample3
|
||||||
|
. initialization
|
||||||
|
. methodOneTest
|
||||||
|
. m2 This is methodTwo
|
||||||
|
|
||||||
|
OK (3 tests)
|
||||||
|
*///:~
|
||||||
75
src/annotations/AtUnitExample4.java
Normal file
75
src/annotations/AtUnitExample4.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
//: annotations/AtUnitExample4.java
|
||||||
|
package annotations;
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class AtUnitExample4 {
|
||||||
|
static String theory = "All brontosauruses " +
|
||||||
|
"are thin at one end, much MUCH thicker in the " +
|
||||||
|
"middle, and then thin again at the far end.";
|
||||||
|
private String word;
|
||||||
|
private Random rand = new Random(); // Time-based seed
|
||||||
|
public AtUnitExample4(String word) { this.word = word; }
|
||||||
|
public String getWord() { return word; }
|
||||||
|
public String scrambleWord() {
|
||||||
|
List<Character> chars = new ArrayList<Character>();
|
||||||
|
for(Character c : word.toCharArray()) {
|
||||||
|
chars.add(c);
|
||||||
|
}
|
||||||
|
Collections.shuffle(chars, rand);
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for(char ch : chars) {
|
||||||
|
result.append(ch);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
@TestProperty static List<String> input =
|
||||||
|
Arrays.asList(theory.split(" "));
|
||||||
|
@TestProperty
|
||||||
|
static Iterator<String> words = input.iterator();
|
||||||
|
@TestObjectCreate static AtUnitExample4 create() {
|
||||||
|
if(words.hasNext()) {
|
||||||
|
return new AtUnitExample4(words.next());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test boolean words() {
|
||||||
|
print("'" + getWord() + "'");
|
||||||
|
return getWord().equals("are");
|
||||||
|
}
|
||||||
|
@Test boolean scramble1() {
|
||||||
|
// Change to a specific seed to get verifiable results:
|
||||||
|
rand = new Random(47);
|
||||||
|
print("'" + getWord() + "'");
|
||||||
|
String scrambled = scrambleWord();
|
||||||
|
print(scrambled);
|
||||||
|
return scrambled.equals("lAl");
|
||||||
|
}
|
||||||
|
@Test boolean scramble2() {
|
||||||
|
rand = new Random(74);
|
||||||
|
print("'" + getWord() + "'");
|
||||||
|
String scrambled = scrambleWord();
|
||||||
|
print(scrambled);
|
||||||
|
return scrambled.equals("tsaeborornussu");
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.out.println("starting");
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExample4");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
starting
|
||||||
|
annotations.AtUnitExample4
|
||||||
|
. scramble1 'All'
|
||||||
|
lAl
|
||||||
|
|
||||||
|
. scramble2 'brontosauruses'
|
||||||
|
tsaeborornussu
|
||||||
|
|
||||||
|
. words 'are'
|
||||||
|
|
||||||
|
OK (3 tests)
|
||||||
|
*///:~
|
||||||
52
src/annotations/AtUnitExample5.java
Normal file
52
src/annotations/AtUnitExample5.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//: annotations/AtUnitExample5.java
|
||||||
|
package annotations;
|
||||||
|
import java.io.*;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitExample5 {
|
||||||
|
private String text;
|
||||||
|
public AtUnitExample5(String text) { this.text = text; }
|
||||||
|
public String toString() { return text; }
|
||||||
|
@TestProperty static PrintWriter output;
|
||||||
|
@TestProperty static int counter;
|
||||||
|
@TestObjectCreate static AtUnitExample5 create() {
|
||||||
|
String id = Integer.toString(counter++);
|
||||||
|
try {
|
||||||
|
output = new PrintWriter("Test" + id + ".txt");
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return new AtUnitExample5(id);
|
||||||
|
}
|
||||||
|
@TestObjectCleanup static void
|
||||||
|
cleanup(AtUnitExample5 tobj) {
|
||||||
|
System.out.println("Running cleanup");
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
@Test boolean test1() {
|
||||||
|
output.print("test1");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@Test boolean test2() {
|
||||||
|
output.print("test2");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@Test boolean test3() {
|
||||||
|
output.print("test3");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExample5");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitExample5
|
||||||
|
. test1
|
||||||
|
Running cleanup
|
||||||
|
. test2
|
||||||
|
Running cleanup
|
||||||
|
. test3
|
||||||
|
Running cleanup
|
||||||
|
OK (3 tests)
|
||||||
|
*///:~
|
||||||
22
src/annotations/AtUnitExternalTest.java
Normal file
22
src/annotations/AtUnitExternalTest.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//: annotations/AtUnitExternalTest.java
|
||||||
|
// Creating non-embedded tests.
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AtUnitExternalTest extends AtUnitExample1 {
|
||||||
|
@Test boolean _methodOne() {
|
||||||
|
return methodOne().equals("This is methodOne");
|
||||||
|
}
|
||||||
|
@Test boolean _methodTwo() { return methodTwo() == 2; }
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit AtUnitExternalTest");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.AtUnitExternalTest
|
||||||
|
. _methodOne
|
||||||
|
. _methodTwo This is methodTwo
|
||||||
|
|
||||||
|
OK (2 tests)
|
||||||
|
*///:~
|
||||||
10
src/annotations/ExtractInterface.java
Normal file
10
src/annotations/ExtractInterface.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//: annotations/ExtractInterface.java
|
||||||
|
// APT-based annotation processing.
|
||||||
|
package annotations;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface ExtractInterface {
|
||||||
|
public String value();
|
||||||
|
} ///:~
|
||||||
31
src/annotations/HashSetTest.java
Normal file
31
src/annotations/HashSetTest.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//: annotations/HashSetTest.java
|
||||||
|
package annotations;
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class HashSetTest {
|
||||||
|
HashSet<String> testObject = new HashSet<String>();
|
||||||
|
@Test void initialization() {
|
||||||
|
assert testObject.isEmpty();
|
||||||
|
}
|
||||||
|
@Test void _contains() {
|
||||||
|
testObject.add("one");
|
||||||
|
assert testObject.contains("one");
|
||||||
|
}
|
||||||
|
@Test void _remove() {
|
||||||
|
testObject.add("one");
|
||||||
|
testObject.remove("one");
|
||||||
|
assert testObject.isEmpty();
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit HashSetTest");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.HashSetTest
|
||||||
|
. initialization
|
||||||
|
. _remove
|
||||||
|
. _contains
|
||||||
|
OK (3 tests)
|
||||||
|
*///:~
|
||||||
64
src/annotations/InterfaceExtractorProcessor.java
Normal file
64
src/annotations/InterfaceExtractorProcessor.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//: annotations/InterfaceExtractorProcessor.java
|
||||||
|
// APT-based annotation processing.
|
||||||
|
// {Exec: apt -factory
|
||||||
|
// annotations.InterfaceExtractorProcessorFactory
|
||||||
|
// Multiplier.java -s ../annotations}
|
||||||
|
package annotations;
|
||||||
|
import com.sun.mirror.apt.*;
|
||||||
|
import com.sun.mirror.declaration.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class InterfaceExtractorProcessor
|
||||||
|
implements AnnotationProcessor {
|
||||||
|
private final AnnotationProcessorEnvironment env;
|
||||||
|
private ArrayList<MethodDeclaration> interfaceMethods =
|
||||||
|
new ArrayList<MethodDeclaration>();
|
||||||
|
public InterfaceExtractorProcessor(
|
||||||
|
AnnotationProcessorEnvironment env) { this.env = env; }
|
||||||
|
public void process() {
|
||||||
|
for(TypeDeclaration typeDecl :
|
||||||
|
env.getSpecifiedTypeDeclarations()) {
|
||||||
|
ExtractInterface annot =
|
||||||
|
typeDecl.getAnnotation(ExtractInterface.class);
|
||||||
|
if(annot == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(MethodDeclaration m : typeDecl.getMethods()) {
|
||||||
|
if(m.getModifiers().contains(Modifier.PUBLIC) &&
|
||||||
|
!(m.getModifiers().contains(Modifier.STATIC))) {
|
||||||
|
interfaceMethods.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(interfaceMethods.size() > 0) {
|
||||||
|
try {
|
||||||
|
PrintWriter writer =
|
||||||
|
env.getFiler().createSourceFile(annot.value());
|
||||||
|
writer.println("package " +
|
||||||
|
typeDecl.getPackage().getQualifiedName() +";");
|
||||||
|
writer.println("public interface " +
|
||||||
|
annot.value() + " {");
|
||||||
|
for(MethodDeclaration m : interfaceMethods) {
|
||||||
|
writer.print(" public ");
|
||||||
|
writer.print(m.getReturnType() + " ");
|
||||||
|
writer.print(m.getSimpleName() + " (");
|
||||||
|
int i = 0;
|
||||||
|
for(ParameterDeclaration parm :
|
||||||
|
m.getParameters()) {
|
||||||
|
writer.print(parm.getType() + " " +
|
||||||
|
parm.getSimpleName());
|
||||||
|
if(++i < m.getParameters().size()) {
|
||||||
|
writer.print(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.println(");");
|
||||||
|
}
|
||||||
|
writer.println("}");
|
||||||
|
writer.close();
|
||||||
|
} catch(IOException ioe) {
|
||||||
|
throw new RuntimeException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
22
src/annotations/InterfaceExtractorProcessorFactory.java
Normal file
22
src/annotations/InterfaceExtractorProcessorFactory.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//: annotations/InterfaceExtractorProcessorFactory.java
|
||||||
|
// APT-based annotation processing.
|
||||||
|
package annotations;
|
||||||
|
import com.sun.mirror.apt.*;
|
||||||
|
import com.sun.mirror.declaration.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class InterfaceExtractorProcessorFactory
|
||||||
|
implements AnnotationProcessorFactory {
|
||||||
|
public AnnotationProcessor getProcessorFor(
|
||||||
|
Set<AnnotationTypeDeclaration> atds,
|
||||||
|
AnnotationProcessorEnvironment env) {
|
||||||
|
return new InterfaceExtractorProcessor(env);
|
||||||
|
}
|
||||||
|
public Collection<String> supportedAnnotationTypes() {
|
||||||
|
return
|
||||||
|
Collections.singleton("annotations.ExtractInterface");
|
||||||
|
}
|
||||||
|
public Collection<String> supportedOptions() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
21
src/annotations/Multiplier.java
Normal file
21
src/annotations/Multiplier.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//: annotations/Multiplier.java
|
||||||
|
// APT-based annotation processing.
|
||||||
|
package annotations;
|
||||||
|
|
||||||
|
@ExtractInterface("IMultiplier")
|
||||||
|
public class Multiplier {
|
||||||
|
public int multiply(int x, int y) {
|
||||||
|
int total = 0;
|
||||||
|
for(int i = 0; i < x; i++) {
|
||||||
|
total = add(total, y);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
private int add(int x, int y) { return x + y; }
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Multiplier m = new Multiplier();
|
||||||
|
System.out.println("11*16 = " + m.multiply(11, 16));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
11*16 = 176
|
||||||
|
*///:~
|
||||||
20
src/annotations/PasswordUtils.java
Normal file
20
src/annotations/PasswordUtils.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package annotations;//: annotations/PasswordUtils.java
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class PasswordUtils {
|
||||||
|
@UseCase(id = 47, description =
|
||||||
|
"Passwords must contain at least one numeric")
|
||||||
|
public boolean validatePassword(String password) {
|
||||||
|
return (password.matches("\\w*\\d\\w*"));
|
||||||
|
}
|
||||||
|
@UseCase(id = 48)
|
||||||
|
public String encryptPassword(String password) {
|
||||||
|
return new StringBuilder(password).reverse().toString();
|
||||||
|
}
|
||||||
|
@UseCase(id = 49, description =
|
||||||
|
"New passwords can't equal previously used ones")
|
||||||
|
public boolean checkForNewPassword(
|
||||||
|
List<String> prevPasswords, String password) {
|
||||||
|
return !prevPasswords.contains(password);
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
9
src/annotations/SimulatingNull.java
Normal file
9
src/annotations/SimulatingNull.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package annotations;//: annotations/SimulatingNull.java
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface SimulatingNull {
|
||||||
|
public int id() default -1;
|
||||||
|
public String description() default "";
|
||||||
|
} ///:~
|
||||||
11
src/annotations/StackL.java
Normal file
11
src/annotations/StackL.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//: annotations/StackL.java
|
||||||
|
// A stack built on a linkedList.
|
||||||
|
package annotations;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class StackL<T> {
|
||||||
|
private LinkedList<T> list = new LinkedList<T>();
|
||||||
|
public void push(T v) { list.addFirst(v); }
|
||||||
|
public T top() { return list.getFirst(); }
|
||||||
|
public T pop() { return list.removeFirst(); }
|
||||||
|
} ///:~
|
||||||
36
src/annotations/StackLStringTest.java
Normal file
36
src/annotations/StackLStringTest.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//: annotations/StackLStringTest.java
|
||||||
|
// Applying @Unit to generics.
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class StackLStringTest extends StackL<String> {
|
||||||
|
@Test void _push() {
|
||||||
|
push("one");
|
||||||
|
assert top().equals("one");
|
||||||
|
push("two");
|
||||||
|
assert top().equals("two");
|
||||||
|
}
|
||||||
|
@Test void _pop() {
|
||||||
|
push("one");
|
||||||
|
push("two");
|
||||||
|
assert pop().equals("two");
|
||||||
|
assert pop().equals("one");
|
||||||
|
}
|
||||||
|
@Test void _top() {
|
||||||
|
push("A");
|
||||||
|
push("B");
|
||||||
|
assert top().equals("B");
|
||||||
|
assert top().equals("B");
|
||||||
|
}
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OSExecute.command(
|
||||||
|
"java net.mindview.atunit.AtUnit StackLStringTest");
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
annotations.StackLStringTest
|
||||||
|
. _push
|
||||||
|
. _pop
|
||||||
|
. _top
|
||||||
|
OK (3 tests)
|
||||||
|
*///:~
|
||||||
10
src/annotations/Testable.java
Normal file
10
src/annotations/Testable.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//: annotations/Testable.java
|
||||||
|
package annotations;
|
||||||
|
import net.mindview.atunit.*;
|
||||||
|
|
||||||
|
public class Testable {
|
||||||
|
public void execute() {
|
||||||
|
System.out.println("Executing..");
|
||||||
|
}
|
||||||
|
@Test void testExecute() { execute(); }
|
||||||
|
} ///:~
|
||||||
9
src/annotations/UseCase.java
Normal file
9
src/annotations/UseCase.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package annotations;//: annotations/UseCase.java
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface UseCase {
|
||||||
|
public int id();
|
||||||
|
public String description() default "no description";
|
||||||
|
} ///:~
|
||||||
30
src/annotations/UseCaseTracker.java
Normal file
30
src/annotations/UseCaseTracker.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package annotations;//: annotations/UseCaseTracker.java
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class UseCaseTracker {
|
||||||
|
public static void
|
||||||
|
trackUseCases(List<Integer> useCases, Class<?> cl) {
|
||||||
|
for(Method m : cl.getDeclaredMethods()) {
|
||||||
|
UseCase uc = m.getAnnotation(UseCase.class);
|
||||||
|
if(uc != null) {
|
||||||
|
System.out.println("Found Use Case:" + uc.id() +
|
||||||
|
" " + uc.description());
|
||||||
|
useCases.remove(new Integer(uc.id()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i : useCases) {
|
||||||
|
System.out.println("Warning: Missing use case-" + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<Integer> useCases = new ArrayList<Integer>();
|
||||||
|
Collections.addAll(useCases, 47, 48, 49, 50);
|
||||||
|
trackUseCases(useCases, PasswordUtils.class);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Found Use Case:47 Passwords must contain at least one numeric
|
||||||
|
Found Use Case:48 no description
|
||||||
|
Found Use Case:49 New passwords can't equal previously used ones
|
||||||
|
Warning: Missing use case-50
|
||||||
|
*///:~
|
||||||
225
src/annotations/build.xml
Normal file
225
src/annotations/build.xml
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<project
|
||||||
|
basedir="."
|
||||||
|
default="run"
|
||||||
|
name="Thinking in Java, 4th Edition by Bruce Eckel (chapter: annotations)">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
build.xml for the source code for the annotations chapter of
|
||||||
|
Thinking in Java, 4th Edition by Bruce Eckel
|
||||||
|
Source code available at http://www.MindView.net
|
||||||
|
See copyright notice in CopyRight.txt
|
||||||
|
|
||||||
|
Ant available from: http://jakarta.apache.org/ant
|
||||||
|
|
||||||
|
To see options, type: ant -p
|
||||||
|
|
||||||
|
This file was automatically generated by AntBuilder
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<condition property="version1.5">
|
||||||
|
<equals arg1="1.5" arg2="${ant.java.version}"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<target name="net_mindview_util">
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
srcdir="${basedir}/../net/mindview/util/">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="net_mindview_atunit">
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
srcdir="${basedir}/../net/mindview/atunit/">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="net_mindview_util,net_mindview_atunit"
|
||||||
|
description="Build all classes in this directory"
|
||||||
|
name="build">
|
||||||
|
<fail message="J2SE5 required" unless="version1.5"/>
|
||||||
|
<echo message="Building 'annotations'"/>
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
debug="true"
|
||||||
|
srcdir="${basedir}">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
<echo message="Build 'annotations' succeeded"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitComposition">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitComposition"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExample1">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExample1"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExample2">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExample2"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExample3">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExample3"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExample4">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExample4"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExample5">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExample5"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AtUnitExternalTest">
|
||||||
|
<java
|
||||||
|
classname="annotations.AtUnitExternalTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="HashSetTest">
|
||||||
|
<java
|
||||||
|
classname="annotations.HashSetTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="Multiplier">
|
||||||
|
<java
|
||||||
|
classname="annotations.Multiplier"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="StackLStringTest">
|
||||||
|
<java
|
||||||
|
classname="annotations.StackLStringTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="UseCaseTracker">
|
||||||
|
<java
|
||||||
|
classname="UseCaseTracker"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="TableCreator">
|
||||||
|
<java
|
||||||
|
classname="annotations.database.TableCreator"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../annotations/database/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true">
|
||||||
|
<arg line="annotations.database.Member"/>
|
||||||
|
</java>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="InterfaceExtractorProcessor">
|
||||||
|
<exec executable="apt">
|
||||||
|
<arg value="-factory"/>
|
||||||
|
<arg
|
||||||
|
value="annotations.InterfaceExtractorProcessorFactory"/>
|
||||||
|
<arg value="Multiplier.java"/>
|
||||||
|
<arg value="-s"/>
|
||||||
|
<arg value="../annotations"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="TableCreationProcessorFactory">
|
||||||
|
<exec executable="apt">
|
||||||
|
<arg value="-factory"/>
|
||||||
|
<arg
|
||||||
|
value="annotations.database.TableCreationProcessorFactory"/>
|
||||||
|
<arg value="database/Member.java"/>
|
||||||
|
<arg value="-s"/>
|
||||||
|
<arg value="database"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="build"
|
||||||
|
description="Compile and run"
|
||||||
|
name="run">
|
||||||
|
<touch file="failures"/>
|
||||||
|
<antcall target="AtUnitComposition"/>
|
||||||
|
<antcall target="AtUnitExample1"/>
|
||||||
|
<antcall target="AtUnitExample2"/>
|
||||||
|
<antcall target="AtUnitExample3"/>
|
||||||
|
<antcall target="AtUnitExample4"/>
|
||||||
|
<antcall target="AtUnitExample5"/>
|
||||||
|
<antcall target="AtUnitExternalTest"/>
|
||||||
|
<antcall target="HashSetTest"/>
|
||||||
|
<antcall target="Multiplier"/>
|
||||||
|
<antcall target="StackLStringTest"/>
|
||||||
|
<antcall target="UseCaseTracker"/>
|
||||||
|
<antcall target="TableCreator"/>
|
||||||
|
<antcall target="InterfaceExtractorProcessor"/>
|
||||||
|
<antcall target="TableCreationProcessorFactory"/>
|
||||||
|
<delete file="failures"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target description="delete all byproducts" name="clean">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/*Output.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/log.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="failures"/>
|
||||||
|
</delete>
|
||||||
|
<echo message="clean successful"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
||||||
|
|
||||||
11
src/annotations/database/Constraints.java
Normal file
11
src/annotations/database/Constraints.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//: annotations/database/Constraints.java
|
||||||
|
package annotations.database;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Constraints {
|
||||||
|
boolean primaryKey() default false;
|
||||||
|
boolean allowNull() default true;
|
||||||
|
boolean unique() default false;
|
||||||
|
} ///:~
|
||||||
9
src/annotations/database/DBTable.java
Normal file
9
src/annotations/database/DBTable.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//: annotations/database/DBTable.java
|
||||||
|
package annotations.database;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE) // Applies to classes only
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface DBTable {
|
||||||
|
public String name() default "";
|
||||||
|
} ///:~
|
||||||
18
src/annotations/database/Member.java
Normal file
18
src/annotations/database/Member.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//: annotations/database/Member.java
|
||||||
|
package annotations.database;
|
||||||
|
|
||||||
|
@DBTable(name = "MEMBER")
|
||||||
|
public class Member {
|
||||||
|
@SQLString(30) String firstName;
|
||||||
|
@SQLString(50) String lastName;
|
||||||
|
@SQLInteger Integer age;
|
||||||
|
@SQLString(value = 30,
|
||||||
|
constraints = @Constraints(primaryKey = true))
|
||||||
|
String handle;
|
||||||
|
static int memberCount;
|
||||||
|
public String getHandle() { return handle; }
|
||||||
|
public String getFirstName() { return firstName; }
|
||||||
|
public String getLastName() { return lastName; }
|
||||||
|
public String toString() { return handle; }
|
||||||
|
public Integer getAge() { return age; }
|
||||||
|
} ///:~
|
||||||
10
src/annotations/database/SQLInteger.java
Normal file
10
src/annotations/database/SQLInteger.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//: annotations/database/SQLInteger.java
|
||||||
|
package annotations.database;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface SQLInteger {
|
||||||
|
String name() default "";
|
||||||
|
Constraints constraints() default @Constraints;
|
||||||
|
} ///:~
|
||||||
11
src/annotations/database/SQLString.java
Normal file
11
src/annotations/database/SQLString.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//: annotations/database/SQLString.java
|
||||||
|
package annotations.database;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface SQLString {
|
||||||
|
int value() default 0;
|
||||||
|
String name() default "";
|
||||||
|
Constraints constraints() default @Constraints;
|
||||||
|
} ///:~
|
||||||
105
src/annotations/database/TableCreationProcessorFactory.java
Normal file
105
src/annotations/database/TableCreationProcessorFactory.java
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
//: annotations/database/TableCreationProcessorFactory.java
|
||||||
|
// The database example using Visitor.
|
||||||
|
// {Exec: apt -factory
|
||||||
|
// annotations.database.TableCreationProcessorFactory
|
||||||
|
// database/Member.java -s database}
|
||||||
|
package annotations.database;
|
||||||
|
import com.sun.mirror.apt.*;
|
||||||
|
import com.sun.mirror.declaration.*;
|
||||||
|
import com.sun.mirror.util.*;
|
||||||
|
import java.util.*;
|
||||||
|
import static com.sun.mirror.util.DeclarationVisitors.*;
|
||||||
|
|
||||||
|
public class TableCreationProcessorFactory
|
||||||
|
implements AnnotationProcessorFactory {
|
||||||
|
public AnnotationProcessor getProcessorFor(
|
||||||
|
Set<AnnotationTypeDeclaration> atds,
|
||||||
|
AnnotationProcessorEnvironment env) {
|
||||||
|
return new TableCreationProcessor(env);
|
||||||
|
}
|
||||||
|
public Collection<String> supportedAnnotationTypes() {
|
||||||
|
return Arrays.asList(
|
||||||
|
"annotations.database.DBTable",
|
||||||
|
"annotations.database.Constraints",
|
||||||
|
"annotations.database.SQLString",
|
||||||
|
"annotations.database.SQLInteger");
|
||||||
|
}
|
||||||
|
public Collection<String> supportedOptions() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
private static class TableCreationProcessor
|
||||||
|
implements AnnotationProcessor {
|
||||||
|
private final AnnotationProcessorEnvironment env;
|
||||||
|
private String sql = "";
|
||||||
|
public TableCreationProcessor(
|
||||||
|
AnnotationProcessorEnvironment env) {
|
||||||
|
this.env = env;
|
||||||
|
}
|
||||||
|
public void process() {
|
||||||
|
for(TypeDeclaration typeDecl :
|
||||||
|
env.getSpecifiedTypeDeclarations()) {
|
||||||
|
typeDecl.accept(getDeclarationScanner(
|
||||||
|
new TableCreationVisitor(), NO_OP));
|
||||||
|
sql = sql.substring(0, sql.length() - 1) + ");";
|
||||||
|
System.out.println("creation SQL is :\n" + sql);
|
||||||
|
sql = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private class TableCreationVisitor
|
||||||
|
extends SimpleDeclarationVisitor {
|
||||||
|
public void visitClassDeclaration(
|
||||||
|
ClassDeclaration d) {
|
||||||
|
DBTable dbTable = d.getAnnotation(DBTable.class);
|
||||||
|
if(dbTable != null) {
|
||||||
|
sql += "CREATE TABLE ";
|
||||||
|
sql += (dbTable.name().length() < 1)
|
||||||
|
? d.getSimpleName().toUpperCase()
|
||||||
|
: dbTable.name();
|
||||||
|
sql += " (";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void visitFieldDeclaration(
|
||||||
|
FieldDeclaration d) {
|
||||||
|
String columnName = "";
|
||||||
|
if(d.getAnnotation(SQLInteger.class) != null) {
|
||||||
|
SQLInteger sInt = d.getAnnotation(
|
||||||
|
SQLInteger.class);
|
||||||
|
// Use field name if name not specified
|
||||||
|
if(sInt.name().length() < 1) {
|
||||||
|
columnName = d.getSimpleName().toUpperCase();
|
||||||
|
} else {
|
||||||
|
columnName = sInt.name();
|
||||||
|
}
|
||||||
|
sql += "\n " + columnName + " INT" +
|
||||||
|
getConstraints(sInt.constraints()) + ",";
|
||||||
|
}
|
||||||
|
if(d.getAnnotation(SQLString.class) != null) {
|
||||||
|
SQLString sString = d.getAnnotation(
|
||||||
|
SQLString.class);
|
||||||
|
// Use field name if name not specified.
|
||||||
|
if(sString.name().length() < 1) {
|
||||||
|
columnName = d.getSimpleName().toUpperCase();
|
||||||
|
} else {
|
||||||
|
columnName = sString.name();
|
||||||
|
}
|
||||||
|
sql += "\n " + columnName + " VARCHAR(" +
|
||||||
|
sString.value() + ")" +
|
||||||
|
getConstraints(sString.constraints()) + ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getConstraints(Constraints con) {
|
||||||
|
String constraints = "";
|
||||||
|
if(!con.allowNull()) {
|
||||||
|
constraints += " NOT NULL";
|
||||||
|
}
|
||||||
|
if(con.primaryKey()) {
|
||||||
|
constraints += " PRIMARY KEY";
|
||||||
|
}
|
||||||
|
if(con.unique()) {
|
||||||
|
constraints += " UNIQUE";
|
||||||
|
}
|
||||||
|
return constraints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
103
src/annotations/database/TableCreator.java
Normal file
103
src/annotations/database/TableCreator.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
//: annotations/database/TableCreator.java
|
||||||
|
// Reflection-based annotation processor.
|
||||||
|
// {Args: annotations.database.Member}
|
||||||
|
package annotations.database;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TableCreator {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
if(args.length < 1) {
|
||||||
|
System.out.println("arguments: annotated classes");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
for(String className : args) {
|
||||||
|
Class<?> cl = Class.forName(className);
|
||||||
|
DBTable dbTable = cl.getAnnotation(DBTable.class);
|
||||||
|
if(dbTable == null) {
|
||||||
|
System.out.println(
|
||||||
|
"No DBTable annotations in class " + className);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String tableName = dbTable.name();
|
||||||
|
// If the name is empty, use the Class name:
|
||||||
|
if(tableName.length() < 1) {
|
||||||
|
tableName = cl.getName().toUpperCase();
|
||||||
|
}
|
||||||
|
List<String> columnDefs = new ArrayList<String>();
|
||||||
|
for(Field field : cl.getDeclaredFields()) {
|
||||||
|
String columnName = null;
|
||||||
|
Annotation[] anns = field.getDeclaredAnnotations();
|
||||||
|
if(anns.length < 1) {
|
||||||
|
continue; // Not a db table column
|
||||||
|
}
|
||||||
|
if(anns[0] instanceof SQLInteger) {
|
||||||
|
SQLInteger sInt = (SQLInteger) anns[0];
|
||||||
|
// Use field name if name not specified
|
||||||
|
if(sInt.name().length() < 1) {
|
||||||
|
columnName = field.getName().toUpperCase();
|
||||||
|
} else {
|
||||||
|
columnName = sInt.name();
|
||||||
|
}
|
||||||
|
columnDefs.add(columnName + " INT" +
|
||||||
|
getConstraints(sInt.constraints()));
|
||||||
|
}
|
||||||
|
if(anns[0] instanceof SQLString) {
|
||||||
|
SQLString sString = (SQLString) anns[0];
|
||||||
|
// Use field name if name not specified.
|
||||||
|
if(sString.name().length() < 1) {
|
||||||
|
columnName = field.getName().toUpperCase();
|
||||||
|
} else {
|
||||||
|
columnName = sString.name();
|
||||||
|
}
|
||||||
|
columnDefs.add(columnName + " VARCHAR(" +
|
||||||
|
sString.value() + ")" +
|
||||||
|
getConstraints(sString.constraints()));
|
||||||
|
}
|
||||||
|
StringBuilder createCommand = new StringBuilder(
|
||||||
|
"CREATE TABLE " + tableName + "(");
|
||||||
|
for(String columnDef : columnDefs) {
|
||||||
|
createCommand.append("\n " + columnDef + ",");
|
||||||
|
}
|
||||||
|
// Remove trailing comma
|
||||||
|
String tableCreate = createCommand.substring(
|
||||||
|
0, createCommand.length() - 1) + ");";
|
||||||
|
System.out.println("Table Creation SQL for " +
|
||||||
|
className + " is :\n" + tableCreate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static String getConstraints(Constraints con) {
|
||||||
|
String constraints = "";
|
||||||
|
if(!con.allowNull()) {
|
||||||
|
constraints += " NOT NULL";
|
||||||
|
}
|
||||||
|
if(con.primaryKey()) {
|
||||||
|
constraints += " PRIMARY KEY";
|
||||||
|
}
|
||||||
|
if(con.unique()) {
|
||||||
|
constraints += " UNIQUE";
|
||||||
|
}
|
||||||
|
return constraints;
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Table Creation SQL for annotations.database.Member is :
|
||||||
|
CREATE TABLE MEMBER(
|
||||||
|
FIRSTNAME VARCHAR(30));
|
||||||
|
Table Creation SQL for annotations.database.Member is :
|
||||||
|
CREATE TABLE MEMBER(
|
||||||
|
FIRSTNAME VARCHAR(30),
|
||||||
|
LASTNAME VARCHAR(50));
|
||||||
|
Table Creation SQL for annotations.database.Member is :
|
||||||
|
CREATE TABLE MEMBER(
|
||||||
|
FIRSTNAME VARCHAR(30),
|
||||||
|
LASTNAME VARCHAR(50),
|
||||||
|
AGE INT);
|
||||||
|
Table Creation SQL for annotations.database.Member is :
|
||||||
|
CREATE TABLE MEMBER(
|
||||||
|
FIRSTNAME VARCHAR(30),
|
||||||
|
LASTNAME VARCHAR(50),
|
||||||
|
AGE INT,
|
||||||
|
HANDLE VARCHAR(30) PRIMARY KEY);
|
||||||
|
*///:~
|
||||||
8
src/annotations/database/Uniqueness.java
Normal file
8
src/annotations/database/Uniqueness.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
//: annotations/database/Uniqueness.java
|
||||||
|
// Sample of nested annotations
|
||||||
|
package annotations.database;
|
||||||
|
|
||||||
|
public @interface Uniqueness {
|
||||||
|
Constraints constraints()
|
||||||
|
default @Constraints(unique=true);
|
||||||
|
} ///:~
|
||||||
20
src/arrays/AlphabeticSearch.java
Normal file
20
src/arrays/AlphabeticSearch.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package arrays;//: arrays/AlphabeticSearch.java
|
||||||
|
// Searching with a Comparator.
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class AlphabeticSearch {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String[] sa = Generated.array(new String[30],
|
||||||
|
new RandomGenerator.String(5));
|
||||||
|
Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);
|
||||||
|
System.out.println(Arrays.toString(sa));
|
||||||
|
int index = Arrays.binarySearch(sa, sa[10],
|
||||||
|
String.CASE_INSENSITIVE_ORDER);
|
||||||
|
System.out.println("Index: "+ index + "\n"+ sa[index]);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[bkIna, cQrGs, cXZJo, dLsmw, eGZMm, EqUCB, gwsqP, hKcxr, HLGEa, HqXum, HxxHv, JMRoE, JmzMs, Mesbt, MNvqe, nyGcF, ogoYW, OneOE, OWZnT, RFJQA, rUkZP, sgqia, slJrL, suEcU, uTpnX, vpfFv, WHkjU, xxEAJ, YNzbr, zDyCy]
|
||||||
|
Index: 10
|
||||||
|
HxxHv
|
||||||
|
*///:~
|
||||||
13
src/arrays/ArrayOfGenericType.java
Normal file
13
src/arrays/ArrayOfGenericType.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package arrays;//: arrays/ArrayOfGenericType.java
|
||||||
|
// Arrays of generic types won't compile.
|
||||||
|
|
||||||
|
public class ArrayOfGenericType<T> {
|
||||||
|
T[] array; // OK
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public ArrayOfGenericType(int size) {
|
||||||
|
//! array = new T[size]; // Illegal
|
||||||
|
array = (T[])new Object[size]; // "unchecked" Warning
|
||||||
|
}
|
||||||
|
// Illegal:
|
||||||
|
//! public <U> U[] makeArray() { return new U[10]; }
|
||||||
|
} ///:~
|
||||||
29
src/arrays/ArrayOfGenerics.java
Normal file
29
src/arrays/ArrayOfGenerics.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package arrays;//: arrays/ArrayOfGenerics.java
|
||||||
|
// It is possible to create arrays of generics.
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ArrayOfGenerics {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<String>[] ls;
|
||||||
|
List[] la = new List[10];
|
||||||
|
ls = (List<String>[])la; // "Unchecked" warning
|
||||||
|
ls[0] = new ArrayList<String>();
|
||||||
|
// Compile-time checking produces an error:
|
||||||
|
//! ls[1] = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
// The problem: List<String> is a subtype of Object
|
||||||
|
Object[] objects = ls; // So assignment is OK
|
||||||
|
// Compiles and runs without complaint:
|
||||||
|
objects[1] = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
// However, if your needs are straightforward it is
|
||||||
|
// possible to create an array of generics, albeit
|
||||||
|
// with an "unchecked" warning:
|
||||||
|
List<BerylliumSphere>[] spheres =
|
||||||
|
(List<BerylliumSphere>[])new List[10];
|
||||||
|
for(int i = 0; i < spheres.length; i++) {
|
||||||
|
spheres[i] = new ArrayList<BerylliumSphere>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
71
src/arrays/ArrayOptions.java
Normal file
71
src/arrays/ArrayOptions.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package arrays;//: arrays/ArrayOptions.java
|
||||||
|
// Initialization & re-assignment of arrays.
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class ArrayOptions {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Arrays of objects:
|
||||||
|
BerylliumSphere[] a; // Local uninitialized variable
|
||||||
|
BerylliumSphere[] b = new BerylliumSphere[5];
|
||||||
|
// The references inside the array are
|
||||||
|
// automatically initialized to null:
|
||||||
|
print("b: " + Arrays.toString(b));
|
||||||
|
BerylliumSphere[] c = new BerylliumSphere[4];
|
||||||
|
for(int i = 0; i < c.length; i++) {
|
||||||
|
if(c[i] == null) // Can test for null reference
|
||||||
|
{
|
||||||
|
c[i] = new BerylliumSphere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Aggregate initialization:
|
||||||
|
BerylliumSphere[] d = { new BerylliumSphere(),
|
||||||
|
new BerylliumSphere(), new BerylliumSphere()
|
||||||
|
};
|
||||||
|
// Dynamic aggregate initialization:
|
||||||
|
a = new BerylliumSphere[]{
|
||||||
|
new BerylliumSphere(), new BerylliumSphere(),
|
||||||
|
};
|
||||||
|
// (Trailing comma is optional in both cases)
|
||||||
|
print("a.length = " + a.length);
|
||||||
|
print("b.length = " + b.length);
|
||||||
|
print("c.length = " + c.length);
|
||||||
|
print("d.length = " + d.length);
|
||||||
|
a = d;
|
||||||
|
print("a.length = " + a.length);
|
||||||
|
|
||||||
|
// Arrays of primitives:
|
||||||
|
int[] e; // Null reference
|
||||||
|
int[] f = new int[5];
|
||||||
|
// The primitives inside the array are
|
||||||
|
// automatically initialized to zero:
|
||||||
|
print("f: " + Arrays.toString(f));
|
||||||
|
int[] g = new int[4];
|
||||||
|
for(int i = 0; i < g.length; i++) {
|
||||||
|
g[i] = i*i;
|
||||||
|
}
|
||||||
|
int[] h = { 11, 47, 93 };
|
||||||
|
// Compile error: variable e not initialized:
|
||||||
|
//!print("e.length = " + e.length);
|
||||||
|
print("f.length = " + f.length);
|
||||||
|
print("g.length = " + g.length);
|
||||||
|
print("h.length = " + h.length);
|
||||||
|
e = h;
|
||||||
|
print("e.length = " + e.length);
|
||||||
|
e = new int[]{ 1, 2 };
|
||||||
|
print("e.length = " + e.length);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
b: [null, null, null, null, null]
|
||||||
|
a.length = 2
|
||||||
|
b.length = 5
|
||||||
|
c.length = 4
|
||||||
|
d.length = 3
|
||||||
|
a.length = 3
|
||||||
|
f: [0, 0, 0, 0, 0]
|
||||||
|
f.length = 5
|
||||||
|
g.length = 4
|
||||||
|
h.length = 3
|
||||||
|
e.length = 3
|
||||||
|
e.length = 2
|
||||||
|
*///:~
|
||||||
28
src/arrays/ArraySearching.java
Normal file
28
src/arrays/ArraySearching.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package arrays;//: arrays/ArraySearching.java
|
||||||
|
// Using Arrays.binarySearch().
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class ArraySearching {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Generator<Integer> gen =
|
||||||
|
new RandomGenerator.Integer(1000);
|
||||||
|
int[] a = ConvertTo.primitive(
|
||||||
|
Generated.array(new Integer[25], gen));
|
||||||
|
Arrays.sort(a);
|
||||||
|
print("Sorted array: " + Arrays.toString(a));
|
||||||
|
while(true) {
|
||||||
|
int r = gen.next();
|
||||||
|
int location = Arrays.binarySearch(a, r);
|
||||||
|
if(location >= 0) {
|
||||||
|
print("Location of " + r + " is " + location +
|
||||||
|
", a[" + location + "] = " + a[location]);
|
||||||
|
break; // Out of while loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Sorted array: [128, 140, 200, 207, 258, 258, 278, 288, 322, 429, 511, 520, 522, 551, 555, 589, 693, 704, 809, 861, 861, 868, 916, 961, 998]
|
||||||
|
Location of 322 is 8, a[8] = 322
|
||||||
|
*///:~
|
||||||
19
src/arrays/AssemblingMultidimensionalArrays.java
Normal file
19
src/arrays/AssemblingMultidimensionalArrays.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package arrays;//: arrays/AssemblingMultidimensionalArrays.java
|
||||||
|
// Creating multidimensional arrays.
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AssemblingMultidimensionalArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[][] a;
|
||||||
|
a = new Integer[3][];
|
||||||
|
for(int i = 0; i < a.length; i++) {
|
||||||
|
a[i] = new Integer[3];
|
||||||
|
for(int j = 0; j < a[i].length; j++) {
|
||||||
|
a[i][j] = i * j; // Autoboxing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(Arrays.deepToString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[0, 0, 0], [0, 1, 2], [0, 2, 4]]
|
||||||
|
*///:~
|
||||||
16
src/arrays/AutoboxingArrays.java
Normal file
16
src/arrays/AutoboxingArrays.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package arrays;//: arrays/AutoboxingArrays.java
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AutoboxingArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[][] a = { // Autoboxing:
|
||||||
|
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
|
||||||
|
{ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
|
||||||
|
{ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60 },
|
||||||
|
{ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 },
|
||||||
|
};
|
||||||
|
System.out.println(Arrays.deepToString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80]]
|
||||||
|
*///:~
|
||||||
55
src/arrays/CompType.java
Normal file
55
src/arrays/CompType.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package arrays;//: arrays/CompType.java
|
||||||
|
// Implementing Comparable in a class.
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class CompType implements Comparable<CompType> {
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
private static int count = 1;
|
||||||
|
public CompType(int n1, int n2) {
|
||||||
|
i = n1;
|
||||||
|
j = n2;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
String result = "[i = " + i + ", j = " + j + "]";
|
||||||
|
if(count++ % 3 == 0) {
|
||||||
|
result += "\n";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public int compareTo(CompType rv) {
|
||||||
|
return (i < rv.i ? -1 : (i == rv.i ? 0 : 1));
|
||||||
|
}
|
||||||
|
private static Random r = new Random(47);
|
||||||
|
public static Generator<CompType> generator() {
|
||||||
|
return new Generator<CompType>() {
|
||||||
|
public CompType next() {
|
||||||
|
return new CompType(r.nextInt(100),r.nextInt(100));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CompType[] a =
|
||||||
|
Generated.array(new CompType[12], generator());
|
||||||
|
print("before sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
Arrays.sort(a);
|
||||||
|
print("after sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
before sorting:
|
||||||
|
[[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
|
||||||
|
, [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
|
||||||
|
, [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
|
||||||
|
, [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
|
||||||
|
]
|
||||||
|
after sorting:
|
||||||
|
[[i = 9, j = 78], [i = 11, j = 22], [i = 16, j = 40]
|
||||||
|
, [i = 20, j = 58], [i = 22, j = 7], [i = 51, j = 89]
|
||||||
|
, [i = 58, j = 55], [i = 61, j = 29], [i = 68, j = 0]
|
||||||
|
, [i = 88, j = 28], [i = 93, j = 61], [i = 98, j = 61]
|
||||||
|
]
|
||||||
|
*///:~
|
||||||
36
src/arrays/ComparatorTest.java
Normal file
36
src/arrays/ComparatorTest.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package arrays;//: arrays/ComparatorTest.java
|
||||||
|
// Implementing a Comparator for a class.
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
class CompTypeComparator implements Comparator<CompType> {
|
||||||
|
public int compare(CompType o1, CompType o2) {
|
||||||
|
return (o1.j < o2.j ? -1 : (o1.j == o2.j ? 0 : 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ComparatorTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CompType[] a = Generated.array(
|
||||||
|
new CompType[12], CompType.generator());
|
||||||
|
print("before sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
Arrays.sort(a, new CompTypeComparator());
|
||||||
|
print("after sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
before sorting:
|
||||||
|
[[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
|
||||||
|
, [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
|
||||||
|
, [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
|
||||||
|
, [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
|
||||||
|
]
|
||||||
|
after sorting:
|
||||||
|
[[i = 68, j = 0], [i = 22, j = 7], [i = 11, j = 22]
|
||||||
|
, [i = 88, j = 28], [i = 61, j = 29], [i = 16, j = 40]
|
||||||
|
, [i = 58, j = 55], [i = 20, j = 58], [i = 93, j = 61]
|
||||||
|
, [i = 98, j = 61], [i = 9, j = 78], [i = 51, j = 89]
|
||||||
|
]
|
||||||
|
*///:~
|
||||||
25
src/arrays/ComparingArrays.java
Normal file
25
src/arrays/ComparingArrays.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package arrays;//: arrays/ComparingArrays.java
|
||||||
|
// Using Arrays.equals()
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class ComparingArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[] a1 = new int[10];
|
||||||
|
int[] a2 = new int[10];
|
||||||
|
Arrays.fill(a1, 47);
|
||||||
|
Arrays.fill(a2, 47);
|
||||||
|
print(Arrays.equals(a1, a2));
|
||||||
|
a2[3] = 11;
|
||||||
|
print(Arrays.equals(a1, a2));
|
||||||
|
String[] s1 = new String[4];
|
||||||
|
Arrays.fill(s1, "Hi");
|
||||||
|
String[] s2 = { new String("Hi"), new String("Hi"),
|
||||||
|
new String("Hi"), new String("Hi") };
|
||||||
|
print(Arrays.equals(s1, s2));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
true
|
||||||
|
false
|
||||||
|
true
|
||||||
|
*///:~
|
||||||
47
src/arrays/ContainerComparison.java
Normal file
47
src/arrays/ContainerComparison.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package arrays;//: arrays/ContainerComparison.java
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
class BerylliumSphere {
|
||||||
|
private static long counter;
|
||||||
|
private final long id = counter++;
|
||||||
|
public String toString() { return "Sphere " + id; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContainerComparison {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BerylliumSphere[] spheres = new BerylliumSphere[10];
|
||||||
|
for(int i = 0; i < 5; i++) {
|
||||||
|
spheres[i] = new BerylliumSphere();
|
||||||
|
}
|
||||||
|
print(Arrays.toString(spheres));
|
||||||
|
print(spheres[4]);
|
||||||
|
|
||||||
|
List<BerylliumSphere> sphereList =
|
||||||
|
new ArrayList<BerylliumSphere>();
|
||||||
|
for(int i = 0; i < 5; i++) {
|
||||||
|
sphereList.add(new BerylliumSphere());
|
||||||
|
}
|
||||||
|
print(sphereList);
|
||||||
|
print(sphereList.get(4));
|
||||||
|
|
||||||
|
int[] integers = { 0, 1, 2, 3, 4, 5 };
|
||||||
|
print(Arrays.toString(integers));
|
||||||
|
print(integers[4]);
|
||||||
|
|
||||||
|
List<Integer> intList = new ArrayList<Integer>(
|
||||||
|
Arrays.asList(0, 1, 2, 3, 4, 5));
|
||||||
|
intList.add(97);
|
||||||
|
print(intList);
|
||||||
|
print(intList.get(4));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[Sphere 0, Sphere 1, Sphere 2, Sphere 3, Sphere 4, null, null, null, null, null]
|
||||||
|
Sphere 4
|
||||||
|
[Sphere 5, Sphere 6, Sphere 7, Sphere 8, Sphere 9]
|
||||||
|
Sphere 9
|
||||||
|
[0, 1, 2, 3, 4, 5]
|
||||||
|
4
|
||||||
|
[0, 1, 2, 3, 4, 5, 97]
|
||||||
|
4
|
||||||
|
*///:~
|
||||||
42
src/arrays/CopyingArrays.java
Normal file
42
src/arrays/CopyingArrays.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package arrays;//: arrays/CopyingArrays.java
|
||||||
|
// Using System.arraycopy()
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class CopyingArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[] i = new int[7];
|
||||||
|
int[] j = new int[10];
|
||||||
|
Arrays.fill(i, 47);
|
||||||
|
Arrays.fill(j, 99);
|
||||||
|
print("i = " + Arrays.toString(i));
|
||||||
|
print("j = " + Arrays.toString(j));
|
||||||
|
System.arraycopy(i, 0, j, 0, i.length);
|
||||||
|
print("j = " + Arrays.toString(j));
|
||||||
|
int[] k = new int[5];
|
||||||
|
Arrays.fill(k, 103);
|
||||||
|
System.arraycopy(i, 0, k, 0, k.length);
|
||||||
|
print("k = " + Arrays.toString(k));
|
||||||
|
Arrays.fill(k, 103);
|
||||||
|
System.arraycopy(k, 0, i, 0, k.length);
|
||||||
|
print("i = " + Arrays.toString(i));
|
||||||
|
// Objects:
|
||||||
|
Integer[] u = new Integer[10];
|
||||||
|
Integer[] v = new Integer[5];
|
||||||
|
Arrays.fill(u, new Integer(47));
|
||||||
|
Arrays.fill(v, new Integer(99));
|
||||||
|
print("u = " + Arrays.toString(u));
|
||||||
|
print("v = " + Arrays.toString(v));
|
||||||
|
System.arraycopy(v, 0, u, u.length/2, v.length);
|
||||||
|
print("u = " + Arrays.toString(u));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
i = [47, 47, 47, 47, 47, 47, 47]
|
||||||
|
j = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
|
||||||
|
j = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]
|
||||||
|
k = [47, 47, 47, 47, 47]
|
||||||
|
i = [103, 103, 103, 103, 103, 47, 47]
|
||||||
|
u = [47, 47, 47, 47, 47, 47, 47, 47, 47, 47]
|
||||||
|
v = [99, 99, 99, 99, 99]
|
||||||
|
u = [47, 47, 47, 47, 47, 99, 99, 99, 99, 99]
|
||||||
|
*///:~
|
||||||
51
src/arrays/FillingArrays.java
Normal file
51
src/arrays/FillingArrays.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package arrays;//: arrays/FillingArrays.java
|
||||||
|
// Using Arrays.fill()
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class FillingArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int size = 6;
|
||||||
|
boolean[] a1 = new boolean[size];
|
||||||
|
byte[] a2 = new byte[size];
|
||||||
|
char[] a3 = new char[size];
|
||||||
|
short[] a4 = new short[size];
|
||||||
|
int[] a5 = new int[size];
|
||||||
|
long[] a6 = new long[size];
|
||||||
|
float[] a7 = new float[size];
|
||||||
|
double[] a8 = new double[size];
|
||||||
|
String[] a9 = new String[size];
|
||||||
|
Arrays.fill(a1, true);
|
||||||
|
print("a1 = " + Arrays.toString(a1));
|
||||||
|
Arrays.fill(a2, (byte)11);
|
||||||
|
print("a2 = " + Arrays.toString(a2));
|
||||||
|
Arrays.fill(a3, 'x');
|
||||||
|
print("a3 = " + Arrays.toString(a3));
|
||||||
|
Arrays.fill(a4, (short)17);
|
||||||
|
print("a4 = " + Arrays.toString(a4));
|
||||||
|
Arrays.fill(a5, 19);
|
||||||
|
print("a5 = " + Arrays.toString(a5));
|
||||||
|
Arrays.fill(a6, 23);
|
||||||
|
print("a6 = " + Arrays.toString(a6));
|
||||||
|
Arrays.fill(a7, 29);
|
||||||
|
print("a7 = " + Arrays.toString(a7));
|
||||||
|
Arrays.fill(a8, 47);
|
||||||
|
print("a8 = " + Arrays.toString(a8));
|
||||||
|
Arrays.fill(a9, "Hello");
|
||||||
|
print("a9 = " + Arrays.toString(a9));
|
||||||
|
// Manipulating ranges:
|
||||||
|
Arrays.fill(a9, 3, 5, "World");
|
||||||
|
print("a9 = " + Arrays.toString(a9));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
a1 = [true, true, true, true, true, true]
|
||||||
|
a2 = [11, 11, 11, 11, 11, 11]
|
||||||
|
a3 = [x, x, x, x, x, x]
|
||||||
|
a4 = [17, 17, 17, 17, 17, 17]
|
||||||
|
a5 = [19, 19, 19, 19, 19, 19]
|
||||||
|
a6 = [23, 23, 23, 23, 23, 23]
|
||||||
|
a7 = [29.0, 29.0, 29.0, 29.0, 29.0, 29.0]
|
||||||
|
a8 = [47.0, 47.0, 47.0, 47.0, 47.0, 47.0]
|
||||||
|
a9 = [Hello, Hello, Hello, Hello, Hello, Hello]
|
||||||
|
a9 = [Hello, Hello, Hello, World, World, Hello]
|
||||||
|
*///:~
|
||||||
33
src/arrays/GeneratorsTest.java
Normal file
33
src/arrays/GeneratorsTest.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package arrays;//: arrays/GeneratorsTest.java
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class GeneratorsTest {
|
||||||
|
public static int size = 10;
|
||||||
|
public static void test(Class<?> surroundingClass) {
|
||||||
|
for(Class<?> type : surroundingClass.getClasses()) {
|
||||||
|
System.out.print(type.getSimpleName() + ": ");
|
||||||
|
try {
|
||||||
|
Generator<?> g = (Generator<?>)type.newInstance();
|
||||||
|
for(int i = 0; i < size; i++) {
|
||||||
|
System.out.printf(g.next() + " ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
test(CountingGenerator.class);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Double: 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
|
||||||
|
Float: 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
|
||||||
|
Long: 0 1 2 3 4 5 6 7 8 9
|
||||||
|
Integer: 0 1 2 3 4 5 6 7 8 9
|
||||||
|
Short: 0 1 2 3 4 5 6 7 8 9
|
||||||
|
String: abcdefg hijklmn opqrstu vwxyzAB CDEFGHI JKLMNOP QRSTUVW XYZabcd efghijk lmnopqr
|
||||||
|
Character: a b c d e f g h i j
|
||||||
|
Byte: 0 1 2 3 4 5 6 7 8 9
|
||||||
|
Boolean: true false true false true false true false true false
|
||||||
|
*///:~
|
||||||
42
src/arrays/IceCream.java
Normal file
42
src/arrays/IceCream.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package arrays;//: arrays/IceCream.java
|
||||||
|
// Returning arrays from methods.
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class IceCream {
|
||||||
|
private static Random rand = new Random(47);
|
||||||
|
static final String[] FLAVORS = {
|
||||||
|
"Chocolate", "Strawberry", "Vanilla Fudge Swirl",
|
||||||
|
"Mint Chip", "Mocha Almond Fudge", "Rum Raisin",
|
||||||
|
"Praline Cream", "Mud Pie"
|
||||||
|
};
|
||||||
|
public static String[] flavorSet(int n) {
|
||||||
|
if(n > FLAVORS.length) {
|
||||||
|
throw new IllegalArgumentException("Set too big");
|
||||||
|
}
|
||||||
|
String[] results = new String[n];
|
||||||
|
boolean[] picked = new boolean[FLAVORS.length];
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
int t;
|
||||||
|
do {
|
||||||
|
t = rand.nextInt(FLAVORS.length);
|
||||||
|
}
|
||||||
|
while(picked[t]);
|
||||||
|
results[i] = FLAVORS[t];
|
||||||
|
picked[t] = true;
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for(int i = 0; i < 7; i++) {
|
||||||
|
System.out.println(Arrays.toString(flavorSet(3)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[Rum Raisin, Mint Chip, Mocha Almond Fudge]
|
||||||
|
[Chocolate, Strawberry, Mocha Almond Fudge]
|
||||||
|
[Strawberry, Mint Chip, Mocha Almond Fudge]
|
||||||
|
[Rum Raisin, Vanilla Fudge Swirl, Mud Pie]
|
||||||
|
[Vanilla Fudge Swirl, Chocolate, Mocha Almond Fudge]
|
||||||
|
[Praline Cream, Strawberry, Mocha Almond Fudge]
|
||||||
|
[Mocha Almond Fudge, Strawberry, Mint Chip]
|
||||||
|
*///:~
|
||||||
29
src/arrays/MultiDimWrapperArray.java
Normal file
29
src/arrays/MultiDimWrapperArray.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package arrays;//: arrays/MultiDimWrapperArray.java
|
||||||
|
// Multidimensional arrays of "wrapper" objects.
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MultiDimWrapperArray {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[][] a1 = { // Autoboxing
|
||||||
|
{ 1, 2, 3, },
|
||||||
|
{ 4, 5, 6, },
|
||||||
|
};
|
||||||
|
Double[][][] a2 = { // Autoboxing
|
||||||
|
{ { 1.1, 2.2 }, { 3.3, 4.4 } },
|
||||||
|
{ { 5.5, 6.6 }, { 7.7, 8.8 } },
|
||||||
|
{ { 9.9, 1.2 }, { 2.3, 3.4 } },
|
||||||
|
};
|
||||||
|
String[][] a3 = {
|
||||||
|
{ "The", "Quick", "Sly", "Fox" },
|
||||||
|
{ "Jumped", "Over" },
|
||||||
|
{ "The", "Lazy", "Brown", "Dog", "and", "friend" },
|
||||||
|
};
|
||||||
|
System.out.println("a1: " + Arrays.deepToString(a1));
|
||||||
|
System.out.println("a2: " + Arrays.deepToString(a2));
|
||||||
|
System.out.println("a3: " + Arrays.deepToString(a3));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
a1: [[1, 2, 3], [4, 5, 6]]
|
||||||
|
a2: [[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7, 8.8]], [[9.9, 1.2], [2.3, 3.4]]]
|
||||||
|
a3: [[The, Quick, Sly, Fox], [Jumped, Over], [The, Lazy, Brown, Dog, and, friend]]
|
||||||
|
*///:~
|
||||||
19
src/arrays/MultidimensionalObjectArrays.java
Normal file
19
src/arrays/MultidimensionalObjectArrays.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package arrays;//: arrays/MultidimensionalObjectArrays.java
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MultidimensionalObjectArrays {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
BerylliumSphere[][] spheres = {
|
||||||
|
{ new BerylliumSphere(), new BerylliumSphere() },
|
||||||
|
{ new BerylliumSphere(), new BerylliumSphere(),
|
||||||
|
new BerylliumSphere(), new BerylliumSphere() },
|
||||||
|
{ new BerylliumSphere(), new BerylliumSphere(),
|
||||||
|
new BerylliumSphere(), new BerylliumSphere(),
|
||||||
|
new BerylliumSphere(), new BerylliumSphere(),
|
||||||
|
new BerylliumSphere(), new BerylliumSphere() },
|
||||||
|
};
|
||||||
|
System.out.println(Arrays.deepToString(spheres));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[Sphere 0, Sphere 1], [Sphere 2, Sphere 3, Sphere 4, Sphere 5], [Sphere 6, Sphere 7, Sphere 8, Sphere 9, Sphere 10, Sphere 11, Sphere 12, Sphere 13]]
|
||||||
|
*///:~
|
||||||
15
src/arrays/MultidimensionalPrimitiveArray.java
Normal file
15
src/arrays/MultidimensionalPrimitiveArray.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package arrays;//: arrays/MultidimensionalPrimitiveArray.java
|
||||||
|
// Creating multidimensional arrays.
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MultidimensionalPrimitiveArray {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int[][] a = {
|
||||||
|
{ 1, 2, 3, },
|
||||||
|
{ 4, 5, 6, },
|
||||||
|
};
|
||||||
|
System.out.println(Arrays.deepToString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[1, 2, 3], [4, 5, 6]]
|
||||||
|
*///:~
|
||||||
22
src/arrays/ParameterizedArrayType.java
Normal file
22
src/arrays/ParameterizedArrayType.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package arrays;//: arrays/ParameterizedArrayType.java
|
||||||
|
|
||||||
|
class ClassParameter<T> {
|
||||||
|
public T[] f(T[] arg) { return arg; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class MethodParameter {
|
||||||
|
public static <T> T[] f(T[] arg) { return arg; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ParameterizedArrayType {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[] ints = { 1, 2, 3, 4, 5 };
|
||||||
|
Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
|
||||||
|
Integer[] ints2 =
|
||||||
|
new ClassParameter<Integer>().f(ints);
|
||||||
|
Double[] doubles2 =
|
||||||
|
new ClassParameter<Double>().f(doubles);
|
||||||
|
ints2 = MethodParameter.f(ints);
|
||||||
|
doubles2 = MethodParameter.f(doubles);
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
19
src/arrays/PrimitiveConversionDemonstration.java
Normal file
19
src/arrays/PrimitiveConversionDemonstration.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package arrays;//: arrays/PrimitiveConversionDemonstration.java
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class PrimitiveConversionDemonstration {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[] a = Generated.array(Integer.class,
|
||||||
|
new CountingGenerator.Integer(), 15);
|
||||||
|
int[] b = ConvertTo.primitive(a);
|
||||||
|
System.out.println(Arrays.toString(b));
|
||||||
|
boolean[] c = ConvertTo.primitive(
|
||||||
|
Generated.array(Boolean.class,
|
||||||
|
new CountingGenerator.Boolean(), 7));
|
||||||
|
System.out.println(Arrays.toString(c));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||||
|
[true, false, true, false, true, false, true]
|
||||||
|
*///:~
|
||||||
19
src/arrays/RaggedArray.java
Normal file
19
src/arrays/RaggedArray.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package arrays;//: arrays/RaggedArray.java
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class RaggedArray {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Random rand = new Random(47);
|
||||||
|
// 3-D array with varied-length vectors:
|
||||||
|
int[][][] a = new int[rand.nextInt(7)][][];
|
||||||
|
for(int i = 0; i < a.length; i++) {
|
||||||
|
a[i] = new int[rand.nextInt(5)][];
|
||||||
|
for(int j = 0; j < a[i].length; j++) {
|
||||||
|
a[i][j] = new int[rand.nextInt(5)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(Arrays.deepToString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[], [[0], [0], [0, 0, 0, 0]], [[], [0, 0], [0, 0]], [[0, 0, 0], [0], [0, 0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0], []], [[0], [], [0]]]
|
||||||
|
*///:~
|
||||||
18
src/arrays/RandomGeneratorsTest.java
Normal file
18
src/arrays/RandomGeneratorsTest.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package arrays;//: arrays/RandomGeneratorsTest.java
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class RandomGeneratorsTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
GeneratorsTest.test(RandomGenerator.class);
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Double: 0.73 0.53 0.16 0.19 0.52 0.27 0.26 0.05 0.8 0.76
|
||||||
|
Float: 0.53 0.16 0.53 0.4 0.49 0.25 0.8 0.11 0.02 0.8
|
||||||
|
Long: 7674 8804 8950 7826 4322 896 8033 2984 2344 5810
|
||||||
|
Integer: 8303 3141 7138 6012 9966 8689 7185 6992 5746 3976
|
||||||
|
Short: 3358 20592 284 26791 12834 -8092 13656 29324 -1423 5327
|
||||||
|
String: bkInaMe sbtWHkj UrUkZPg wsqPzDy CyRFJQA HxxHvHq XumcXZJ oogoYWM NvqeuTp nXsgqia
|
||||||
|
Character: x x E A J J m z M s
|
||||||
|
Byte: -60 -17 55 -14 -5 115 39 -37 79 115
|
||||||
|
Boolean: false true false false true true true true true true
|
||||||
|
*///:~
|
||||||
30
src/arrays/Reverse.java
Normal file
30
src/arrays/Reverse.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package arrays;//: arrays/Reverse.java
|
||||||
|
// The Collections.reverseOrder() Comparator
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class Reverse {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CompType[] a = Generated.array(
|
||||||
|
new CompType[12], CompType.generator());
|
||||||
|
print("before sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
Arrays.sort(a, Collections.reverseOrder());
|
||||||
|
print("after sorting:");
|
||||||
|
print(Arrays.toString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
before sorting:
|
||||||
|
[[i = 58, j = 55], [i = 93, j = 61], [i = 61, j = 29]
|
||||||
|
, [i = 68, j = 0], [i = 22, j = 7], [i = 88, j = 28]
|
||||||
|
, [i = 51, j = 89], [i = 9, j = 78], [i = 98, j = 61]
|
||||||
|
, [i = 20, j = 58], [i = 16, j = 40], [i = 11, j = 22]
|
||||||
|
]
|
||||||
|
after sorting:
|
||||||
|
[[i = 98, j = 61], [i = 93, j = 61], [i = 88, j = 28]
|
||||||
|
, [i = 68, j = 0], [i = 61, j = 29], [i = 58, j = 55]
|
||||||
|
, [i = 51, j = 89], [i = 22, j = 7], [i = 20, j = 58]
|
||||||
|
, [i = 16, j = 40], [i = 11, j = 22], [i = 9, j = 78]
|
||||||
|
]
|
||||||
|
*///:~
|
||||||
24
src/arrays/StringSorting.java
Normal file
24
src/arrays/StringSorting.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package arrays;//: arrays/StringSorting.java
|
||||||
|
// Sorting an array of Strings.
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class StringSorting {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String[] sa = Generated.array(new String[20],
|
||||||
|
new RandomGenerator.String(5));
|
||||||
|
print("Before sort: " + Arrays.toString(sa));
|
||||||
|
Arrays.sort(sa);
|
||||||
|
print("After sort: " + Arrays.toString(sa));
|
||||||
|
Arrays.sort(sa, Collections.reverseOrder());
|
||||||
|
print("Reverse sort: " + Arrays.toString(sa));
|
||||||
|
Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);
|
||||||
|
print("Case-insensitive sort: " + Arrays.toString(sa));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
Before sort: [YNzbr, nyGcF, OWZnT, cQrGs, eGZMm, JMRoE, suEcU, OneOE, dLsmw, HLGEa, hKcxr, EqUCB, bkIna, Mesbt, WHkjU, rUkZP, gwsqP, zDyCy, RFJQA, HxxHv]
|
||||||
|
After sort: [EqUCB, HLGEa, HxxHv, JMRoE, Mesbt, OWZnT, OneOE, RFJQA, WHkjU, YNzbr, bkIna, cQrGs, dLsmw, eGZMm, gwsqP, hKcxr, nyGcF, rUkZP, suEcU, zDyCy]
|
||||||
|
Reverse sort: [zDyCy, suEcU, rUkZP, nyGcF, hKcxr, gwsqP, eGZMm, dLsmw, cQrGs, bkIna, YNzbr, WHkjU, RFJQA, OneOE, OWZnT, Mesbt, JMRoE, HxxHv, HLGEa, EqUCB]
|
||||||
|
Case-insensitive sort: [bkIna, cQrGs, dLsmw, eGZMm, EqUCB, gwsqP, hKcxr, HLGEa, HxxHv, JMRoE, Mesbt, nyGcF, OneOE, OWZnT, RFJQA, rUkZP, suEcU, WHkjU, YNzbr, zDyCy]
|
||||||
|
*///:~
|
||||||
45
src/arrays/TestArrayGeneration.java
Normal file
45
src/arrays/TestArrayGeneration.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package arrays;//: arrays/TestArrayGeneration.java
|
||||||
|
// Test the tools that use generators to fill arrays.
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class TestArrayGeneration {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int size = 6;
|
||||||
|
boolean[] a1 = ConvertTo.primitive(Generated.array(
|
||||||
|
Boolean.class, new RandomGenerator.Boolean(), size));
|
||||||
|
print("a1 = " + Arrays.toString(a1));
|
||||||
|
byte[] a2 = ConvertTo.primitive(Generated.array(
|
||||||
|
Byte.class, new RandomGenerator.Byte(), size));
|
||||||
|
print("a2 = " + Arrays.toString(a2));
|
||||||
|
char[] a3 = ConvertTo.primitive(Generated.array(
|
||||||
|
Character.class,
|
||||||
|
new RandomGenerator.Character(), size));
|
||||||
|
print("a3 = " + Arrays.toString(a3));
|
||||||
|
short[] a4 = ConvertTo.primitive(Generated.array(
|
||||||
|
Short.class, new RandomGenerator.Short(), size));
|
||||||
|
print("a4 = " + Arrays.toString(a4));
|
||||||
|
int[] a5 = ConvertTo.primitive(Generated.array(
|
||||||
|
Integer.class, new RandomGenerator.Integer(), size));
|
||||||
|
print("a5 = " + Arrays.toString(a5));
|
||||||
|
long[] a6 = ConvertTo.primitive(Generated.array(
|
||||||
|
Long.class, new RandomGenerator.Long(), size));
|
||||||
|
print("a6 = " + Arrays.toString(a6));
|
||||||
|
float[] a7 = ConvertTo.primitive(Generated.array(
|
||||||
|
Float.class, new RandomGenerator.Float(), size));
|
||||||
|
print("a7 = " + Arrays.toString(a7));
|
||||||
|
double[] a8 = ConvertTo.primitive(Generated.array(
|
||||||
|
Double.class, new RandomGenerator.Double(), size));
|
||||||
|
print("a8 = " + Arrays.toString(a8));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
a1 = [true, false, true, false, false, true]
|
||||||
|
a2 = [104, -79, -76, 126, 33, -64]
|
||||||
|
a3 = [Z, n, T, c, Q, r]
|
||||||
|
a4 = [-13408, 22612, 15401, 15161, -28466, -12603]
|
||||||
|
a5 = [7704, 7383, 7706, 575, 8410, 6342]
|
||||||
|
a6 = [7674, 8804, 8950, 7826, 4322, 896]
|
||||||
|
a7 = [0.01, 0.2, 0.4, 0.79, 0.27, 0.45]
|
||||||
|
a8 = [0.16, 0.87, 0.7, 0.66, 0.87, 0.59]
|
||||||
|
*///:~
|
||||||
19
src/arrays/TestGenerated.java
Normal file
19
src/arrays/TestGenerated.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package arrays;//: arrays/TestGenerated.java
|
||||||
|
import java.util.*;
|
||||||
|
import net.mindview.util.*;
|
||||||
|
|
||||||
|
public class TestGenerated {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Integer[] a = { 9, 8, 7, 6 };
|
||||||
|
System.out.println(Arrays.toString(a));
|
||||||
|
a = Generated.array(a,new CountingGenerator.Integer());
|
||||||
|
System.out.println(Arrays.toString(a));
|
||||||
|
Integer[] b = Generated.array(Integer.class,
|
||||||
|
new CountingGenerator.Integer(), 15);
|
||||||
|
System.out.println(Arrays.toString(b));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[9, 8, 7, 6]
|
||||||
|
[0, 1, 2, 3]
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||||
|
*///:~
|
||||||
12
src/arrays/ThreeDWithNew.java
Normal file
12
src/arrays/ThreeDWithNew.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package arrays;//: arrays/ThreeDWithNew.java
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ThreeDWithNew {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 3-D array with fixed length:
|
||||||
|
int[][][] a = new int[2][2][4];
|
||||||
|
System.out.println(Arrays.deepToString(a));
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
[[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
|
||||||
|
*///:~
|
||||||
330
src/arrays/build.xml
Normal file
330
src/arrays/build.xml
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<project
|
||||||
|
basedir="."
|
||||||
|
default="run"
|
||||||
|
name="Thinking in Java, 4th Edition by Bruce Eckel (chapter: arrays)">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
build.xml for the source code for the arrays chapter of
|
||||||
|
Thinking in Java, 4th Edition by Bruce Eckel
|
||||||
|
Source code available at http://www.MindView.net
|
||||||
|
See copyright notice in CopyRight.txt
|
||||||
|
|
||||||
|
Ant available from: http://jakarta.apache.org/ant
|
||||||
|
|
||||||
|
To see options, type: ant -p
|
||||||
|
|
||||||
|
This file was automatically generated by AntBuilder
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<condition property="version1.5">
|
||||||
|
<equals arg1="1.5" arg2="${ant.java.version}"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<target name="net_mindview_util">
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
srcdir="${basedir}/../net/mindview/util/">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="net_mindview_util"
|
||||||
|
description="Build all classes in this directory"
|
||||||
|
name="build">
|
||||||
|
<fail message="J2SE5 required" unless="version1.5"/>
|
||||||
|
<echo message="Building 'arrays'"/>
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
debug="true"
|
||||||
|
srcdir="${basedir}">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
<echo message="Build 'arrays' succeeded"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AlphabeticSearch">
|
||||||
|
<java
|
||||||
|
classname="AlphabeticSearch"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ArrayOfGenerics">
|
||||||
|
<java
|
||||||
|
classname="ArrayOfGenerics"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ArrayOptions">
|
||||||
|
<java
|
||||||
|
classname="ArrayOptions"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ArraySearching">
|
||||||
|
<java
|
||||||
|
classname="ArraySearching"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AssemblingMultidimensionalArrays">
|
||||||
|
<java
|
||||||
|
classname="AssemblingMultidimensionalArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="AutoboxingArrays">
|
||||||
|
<java
|
||||||
|
classname="AutoboxingArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ComparatorTest">
|
||||||
|
<java
|
||||||
|
classname="ComparatorTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ComparingArrays">
|
||||||
|
<java
|
||||||
|
classname="ComparingArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="CompType">
|
||||||
|
<java
|
||||||
|
classname="CompType"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ContainerComparison">
|
||||||
|
<java
|
||||||
|
classname="ContainerComparison"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="CopyingArrays">
|
||||||
|
<java
|
||||||
|
classname="CopyingArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="FillingArrays">
|
||||||
|
<java
|
||||||
|
classname="FillingArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="GeneratorsTest">
|
||||||
|
<java
|
||||||
|
classname="GeneratorsTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="IceCream">
|
||||||
|
<java
|
||||||
|
classname="IceCream"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="MultidimensionalObjectArrays">
|
||||||
|
<java
|
||||||
|
classname="MultidimensionalObjectArrays"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="MultidimensionalPrimitiveArray">
|
||||||
|
<java
|
||||||
|
classname="MultidimensionalPrimitiveArray"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="MultiDimWrapperArray">
|
||||||
|
<java
|
||||||
|
classname="MultiDimWrapperArray"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ParameterizedArrayType">
|
||||||
|
<java
|
||||||
|
classname="ParameterizedArrayType"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="PrimitiveConversionDemonstration">
|
||||||
|
<java
|
||||||
|
classname="PrimitiveConversionDemonstration"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="RaggedArray">
|
||||||
|
<java
|
||||||
|
classname="RaggedArray"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="RandomGeneratorsTest">
|
||||||
|
<java
|
||||||
|
classname="RandomGeneratorsTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="Reverse">
|
||||||
|
<java
|
||||||
|
classname="Reverse"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="StringSorting">
|
||||||
|
<java
|
||||||
|
classname="StringSorting"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="TestArrayGeneration">
|
||||||
|
<java
|
||||||
|
classname="TestArrayGeneration"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="TestGenerated">
|
||||||
|
<java
|
||||||
|
classname="TestGenerated"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="ThreeDWithNew">
|
||||||
|
<java
|
||||||
|
classname="ThreeDWithNew"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../arrays/"
|
||||||
|
failonerror="true"
|
||||||
|
fork="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="build"
|
||||||
|
description="Compile and run"
|
||||||
|
name="run">
|
||||||
|
<touch file="failures"/>
|
||||||
|
<antcall target="AlphabeticSearch"/>
|
||||||
|
<antcall target="ArrayOfGenerics"/>
|
||||||
|
<antcall target="ArrayOptions"/>
|
||||||
|
<antcall target="ArraySearching"/>
|
||||||
|
<antcall target="AssemblingMultidimensionalArrays"/>
|
||||||
|
<antcall target="AutoboxingArrays"/>
|
||||||
|
<antcall target="ComparatorTest"/>
|
||||||
|
<antcall target="ComparingArrays"/>
|
||||||
|
<antcall target="CompType"/>
|
||||||
|
<antcall target="ContainerComparison"/>
|
||||||
|
<antcall target="CopyingArrays"/>
|
||||||
|
<antcall target="FillingArrays"/>
|
||||||
|
<antcall target="GeneratorsTest"/>
|
||||||
|
<antcall target="IceCream"/>
|
||||||
|
<antcall target="MultidimensionalObjectArrays"/>
|
||||||
|
<antcall target="MultidimensionalPrimitiveArray"/>
|
||||||
|
<antcall target="MultiDimWrapperArray"/>
|
||||||
|
<antcall target="ParameterizedArrayType"/>
|
||||||
|
<antcall target="PrimitiveConversionDemonstration"/>
|
||||||
|
<antcall target="RaggedArray"/>
|
||||||
|
<antcall target="RandomGeneratorsTest"/>
|
||||||
|
<antcall target="Reverse"/>
|
||||||
|
<antcall target="StringSorting"/>
|
||||||
|
<antcall target="TestArrayGeneration"/>
|
||||||
|
<antcall target="TestGenerated"/>
|
||||||
|
<antcall target="ThreeDWithNew"/>
|
||||||
|
<delete file="failures"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target description="delete all byproducts" name="clean">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/*Output.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/log.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="failures"/>
|
||||||
|
</delete>
|
||||||
|
<echo message="clean successful"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
||||||
|
|
||||||
83
src/bangbean/BangBean.java
Normal file
83
src/bangbean/BangBean.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
//: bangbean/BangBean.java
|
||||||
|
// A graphical Bean.
|
||||||
|
package bangbean;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class
|
||||||
|
BangBean extends JPanel implements Serializable {
|
||||||
|
private int xm, ym;
|
||||||
|
private int cSize = 20; // Circle size
|
||||||
|
private String text = "Bang!";
|
||||||
|
private int fontSize = 48;
|
||||||
|
private Color tColor = Color.RED;
|
||||||
|
private ActionListener actionListener;
|
||||||
|
public BangBean() {
|
||||||
|
addMouseListener(new ML());
|
||||||
|
addMouseMotionListener(new MML());
|
||||||
|
}
|
||||||
|
public int getCircleSize() { return cSize; }
|
||||||
|
public void setCircleSize(int newSize) {
|
||||||
|
cSize = newSize;
|
||||||
|
}
|
||||||
|
public String getBangText() { return text; }
|
||||||
|
public void setBangText(String newText) {
|
||||||
|
text = newText;
|
||||||
|
}
|
||||||
|
public int getFontSize() { return fontSize; }
|
||||||
|
public void setFontSize(int newSize) {
|
||||||
|
fontSize = newSize;
|
||||||
|
}
|
||||||
|
public Color getTextColor() { return tColor; }
|
||||||
|
public void setTextColor(Color newColor) {
|
||||||
|
tColor = newColor;
|
||||||
|
}
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
g.setColor(Color.BLACK);
|
||||||
|
g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize);
|
||||||
|
}
|
||||||
|
// This is a unicast listener, which is
|
||||||
|
// the simplest form of listener management:
|
||||||
|
public void addActionListener(ActionListener l)
|
||||||
|
throws TooManyListenersException {
|
||||||
|
if(actionListener != null) {
|
||||||
|
throw new TooManyListenersException();
|
||||||
|
}
|
||||||
|
actionListener = l;
|
||||||
|
}
|
||||||
|
public void removeActionListener(ActionListener l) {
|
||||||
|
actionListener = null;
|
||||||
|
}
|
||||||
|
class ML extends MouseAdapter {
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
Graphics g = getGraphics();
|
||||||
|
g.setColor(tColor);
|
||||||
|
g.setFont(
|
||||||
|
new Font("TimesRoman", Font.BOLD, fontSize));
|
||||||
|
int width = g.getFontMetrics().stringWidth(text);
|
||||||
|
g.drawString(text, (getSize().width - width) /2,
|
||||||
|
getSize().height/2);
|
||||||
|
g.dispose();
|
||||||
|
// Call the listener's method:
|
||||||
|
if(actionListener != null) {
|
||||||
|
actionListener.actionPerformed(
|
||||||
|
new ActionEvent(BangBean.this,
|
||||||
|
ActionEvent.ACTION_PERFORMED, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class MML extends MouseMotionAdapter {
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
xm = e.getX();
|
||||||
|
ym = e.getY();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
return new Dimension(200, 200);
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
32
src/bangbean/BangBeanTest.java
Normal file
32
src/bangbean/BangBeanTest.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//: bangbean/BangBeanTest.java
|
||||||
|
// {Timeout: 5} Abort after 5 seconds when testing
|
||||||
|
package bangbean;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.SwingConsole.*;
|
||||||
|
|
||||||
|
public class BangBeanTest extends JFrame {
|
||||||
|
private JTextField txt = new JTextField(20);
|
||||||
|
// During testing, report actions:
|
||||||
|
class BBL implements ActionListener {
|
||||||
|
private int count = 0;
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
txt.setText("BangBean action "+ count++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public BangBeanTest() {
|
||||||
|
BangBean bb = new BangBean();
|
||||||
|
try {
|
||||||
|
bb.addActionListener(new BBL());
|
||||||
|
} catch(TooManyListenersException e) {
|
||||||
|
txt.setText("Too many listeners");
|
||||||
|
}
|
||||||
|
add(bb);
|
||||||
|
add(BorderLayout.SOUTH, txt);
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
run(new BangBeanTest(), 400, 500);
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
73
src/bangbean/build.xml
Normal file
73
src/bangbean/build.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<project
|
||||||
|
basedir="."
|
||||||
|
default="run"
|
||||||
|
name="Thinking in Java, 4th Edition by Bruce Eckel (chapter: bangbean)">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
build.xml for the source code for the bangbean chapter of
|
||||||
|
Thinking in Java, 4th Edition by Bruce Eckel
|
||||||
|
Source code available at http://www.MindView.net
|
||||||
|
See copyright notice in CopyRight.txt
|
||||||
|
|
||||||
|
Ant available from: http://jakarta.apache.org/ant
|
||||||
|
|
||||||
|
To see options, type: ant -p
|
||||||
|
|
||||||
|
This file was automatically generated by AntBuilder
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<condition property="version1.5">
|
||||||
|
<equals arg1="1.5" arg2="${ant.java.version}"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends=""
|
||||||
|
description="Build all classes in this directory"
|
||||||
|
name="build">
|
||||||
|
<fail message="J2SE5 required" unless="version1.5"/>
|
||||||
|
<echo message="Building 'bangbean'"/>
|
||||||
|
<javac
|
||||||
|
classpath="${basedir}/.."
|
||||||
|
debug="true"
|
||||||
|
srcdir="${basedir}">
|
||||||
|
<compilerarg value="-Xmaxerrs"/>
|
||||||
|
<compilerarg value="10"/>
|
||||||
|
</javac>
|
||||||
|
<echo message="Build 'bangbean' succeeded"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="BangBeanTest">
|
||||||
|
<java
|
||||||
|
classname="bangbean.BangBeanTest"
|
||||||
|
classpath="${java.class.path};${basedir};${basedir}/.."
|
||||||
|
dir="../bangbean/"
|
||||||
|
failonerror="false"
|
||||||
|
fork="true"
|
||||||
|
timeout="5000"/>
|
||||||
|
<echo message="* Exception was expected *"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target
|
||||||
|
depends="build"
|
||||||
|
description="Compile and run"
|
||||||
|
name="run">
|
||||||
|
<touch file="failures"/>
|
||||||
|
<antcall target="BangBeanTest"/>
|
||||||
|
<delete file="failures"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target description="delete all byproducts" name="clean">
|
||||||
|
<delete>
|
||||||
|
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/*Output.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="**/log.txt"/>
|
||||||
|
<fileset dir="${basedir}" includes="failures"/>
|
||||||
|
</delete>
|
||||||
|
<echo message="clean successful"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
||||||
|
|
||||||
92
src/concurrency/ActiveObjectDemo.java
Normal file
92
src/concurrency/ActiveObjectDemo.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package concurrency;//: concurrency/ActiveObjectDemo.java
|
||||||
|
// Can only pass constants, immutables, "disconnected
|
||||||
|
// objects," or other active objects as arguments
|
||||||
|
// to asynch methods.
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.*;
|
||||||
|
import static net.mindview.util.Print.*;
|
||||||
|
|
||||||
|
public class ActiveObjectDemo {
|
||||||
|
private ExecutorService ex =
|
||||||
|
Executors.newSingleThreadExecutor();
|
||||||
|
private Random rand = new Random(47);
|
||||||
|
// Insert a random delay to produce the effect
|
||||||
|
// of a calculation time:
|
||||||
|
private void pause(int factor) {
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(
|
||||||
|
100 + rand.nextInt(factor));
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
print("sleep() interrupted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Future<Integer>
|
||||||
|
calculateInt(final int x, final int y) {
|
||||||
|
return ex.submit(new Callable<Integer>() {
|
||||||
|
public Integer call() {
|
||||||
|
print("starting " + x + " + " + y);
|
||||||
|
pause(500);
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public Future<Float>
|
||||||
|
calculateFloat(final float x, final float y) {
|
||||||
|
return ex.submit(new Callable<Float>() {
|
||||||
|
public Float call() {
|
||||||
|
print("starting " + x + " + " + y);
|
||||||
|
pause(2000);
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void shutdown() { ex.shutdown(); }
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ActiveObjectDemo d1 = new ActiveObjectDemo();
|
||||||
|
// Prevents ConcurrentModificationException:
|
||||||
|
List<Future<?>> results =
|
||||||
|
new CopyOnWriteArrayList<Future<?>>();
|
||||||
|
for(float f = 0.0f; f < 1.0f; f += 0.2f) {
|
||||||
|
results.add(d1.calculateFloat(f, f));
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 5; i++) {
|
||||||
|
results.add(d1.calculateInt(i, i));
|
||||||
|
}
|
||||||
|
print("All asynch calls made");
|
||||||
|
while(results.size() > 0) {
|
||||||
|
for(Future<?> f : results) {
|
||||||
|
if(f.isDone()) {
|
||||||
|
try {
|
||||||
|
print(f.get());
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
results.remove(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d1.shutdown();
|
||||||
|
}
|
||||||
|
} /* Output: (85% match)
|
||||||
|
All asynch calls made
|
||||||
|
starting 0.0 + 0.0
|
||||||
|
starting 0.2 + 0.2
|
||||||
|
0.0
|
||||||
|
starting 0.4 + 0.4
|
||||||
|
0.4
|
||||||
|
starting 0.6 + 0.6
|
||||||
|
0.8
|
||||||
|
starting 0.8 + 0.8
|
||||||
|
1.2
|
||||||
|
starting 0 + 0
|
||||||
|
1.6
|
||||||
|
starting 1 + 1
|
||||||
|
0
|
||||||
|
starting 2 + 2
|
||||||
|
2
|
||||||
|
starting 3 + 3
|
||||||
|
4
|
||||||
|
starting 4 + 4
|
||||||
|
6
|
||||||
|
8
|
||||||
|
*///:~
|
||||||
15
src/concurrency/AtomicEvenGenerator.java
Normal file
15
src/concurrency/AtomicEvenGenerator.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package concurrency;//: concurrency/AtomicEvenGenerator.java
|
||||||
|
// Atomic classes are occasionally useful in regular code.
|
||||||
|
// {RunByHand}
|
||||||
|
import java.util.concurrent.atomic.*;
|
||||||
|
|
||||||
|
public class AtomicEvenGenerator extends IntGenerator {
|
||||||
|
private AtomicInteger currentEvenValue =
|
||||||
|
new AtomicInteger(0);
|
||||||
|
public int next() {
|
||||||
|
return currentEvenValue.addAndGet(2);
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
EvenChecker.test(new AtomicEvenGenerator());
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
33
src/concurrency/AtomicIntegerTest.java
Normal file
33
src/concurrency/AtomicIntegerTest.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package concurrency;//: concurrency/AtomicIntegerTest.java
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AtomicIntegerTest implements Runnable {
|
||||||
|
private AtomicInteger i = new AtomicInteger(0);
|
||||||
|
public int getValue() { return i.get(); }
|
||||||
|
private void evenIncrement() { i.addAndGet(2); }
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
evenIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
public void run() {
|
||||||
|
System.err.println("Aborting");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}, 5000); // Terminate after 5 seconds
|
||||||
|
ExecutorService exec = Executors.newCachedThreadPool();
|
||||||
|
AtomicIntegerTest ait = new AtomicIntegerTest();
|
||||||
|
exec.execute(ait);
|
||||||
|
while(true) {
|
||||||
|
int val = ait.getValue();
|
||||||
|
if(val % 2 != 0) {
|
||||||
|
System.out.println(val);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ///:~
|
||||||
29
src/concurrency/Atomicity.java
Normal file
29
src/concurrency/Atomicity.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package concurrency;//: concurrency/Atomicity.java
|
||||||
|
// {Exec: javap -c Atomicity}
|
||||||
|
|
||||||
|
public class Atomicity {
|
||||||
|
int i;
|
||||||
|
void f1() { i++; }
|
||||||
|
void f2() { i += 3; }
|
||||||
|
} /* Output: (Sample)
|
||||||
|
...
|
||||||
|
void f1();
|
||||||
|
Code:
|
||||||
|
0: aload_0
|
||||||
|
1: dup
|
||||||
|
2: getfield #2; //Field i:I
|
||||||
|
5: iconst_1
|
||||||
|
6: iadd
|
||||||
|
7: putfield #2; //Field i:I
|
||||||
|
10: return
|
||||||
|
|
||||||
|
void f2();
|
||||||
|
Code:
|
||||||
|
0: aload_0
|
||||||
|
1: dup
|
||||||
|
2: getfield #2; //Field i:I
|
||||||
|
5: iconst_3
|
||||||
|
6: iadd
|
||||||
|
7: putfield #2; //Field i:I
|
||||||
|
10: return
|
||||||
|
*///:~
|
||||||
27
src/concurrency/AtomicityTest.java
Normal file
27
src/concurrency/AtomicityTest.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package concurrency;//: concurrency/AtomicityTest.java
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
public class AtomicityTest implements Runnable {
|
||||||
|
private int i = 0;
|
||||||
|
public int getValue() { return i; }
|
||||||
|
private synchronized void evenIncrement() { i++; i++; }
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
evenIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ExecutorService exec = Executors.newCachedThreadPool();
|
||||||
|
AtomicityTest at = new AtomicityTest();
|
||||||
|
exec.execute(at);
|
||||||
|
while(true) {
|
||||||
|
int val = at.getValue();
|
||||||
|
if(val % 2 != 0) {
|
||||||
|
System.out.println(val);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* Output: (Sample)
|
||||||
|
191583767
|
||||||
|
*///:~
|
||||||
57
src/concurrency/AttemptLocking.java
Normal file
57
src/concurrency/AttemptLocking.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package concurrency;//: concurrency/AttemptLocking.java
|
||||||
|
// Locks in the concurrent library allow you
|
||||||
|
// to give up on trying to acquire a lock.
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.locks.*;
|
||||||
|
|
||||||
|
public class AttemptLocking {
|
||||||
|
private ReentrantLock lock = new ReentrantLock();
|
||||||
|
public void untimed() {
|
||||||
|
boolean captured = lock.tryLock();
|
||||||
|
try {
|
||||||
|
System.out.println("tryLock(): " + captured);
|
||||||
|
} finally {
|
||||||
|
if(captured) {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void timed() {
|
||||||
|
boolean captured = false;
|
||||||
|
try {
|
||||||
|
captured = lock.tryLock(2, TimeUnit.SECONDS);
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
System.out.println("tryLock(2, TimeUnit.SECONDS): " +
|
||||||
|
captured);
|
||||||
|
} finally {
|
||||||
|
if(captured) {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final AttemptLocking al = new AttemptLocking();
|
||||||
|
al.untimed(); // True -- lock is available
|
||||||
|
al.timed(); // True -- lock is available
|
||||||
|
// Now create a separate task to grab the lock:
|
||||||
|
new Thread() {
|
||||||
|
{ setDaemon(true); }
|
||||||
|
public void run() {
|
||||||
|
al.lock.lock();
|
||||||
|
System.out.println("acquired");
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
Thread.yield(); // Give the 2nd task a chance
|
||||||
|
al.untimed(); // False -- lock grabbed by task
|
||||||
|
al.timed(); // False -- lock grabbed by task
|
||||||
|
}
|
||||||
|
} /* Output:
|
||||||
|
tryLock(): true
|
||||||
|
tryLock(2, TimeUnit.SECONDS): true
|
||||||
|
acquired
|
||||||
|
tryLock(): false
|
||||||
|
tryLock(2, TimeUnit.SECONDS): false
|
||||||
|
*///:~
|
||||||
212
src/concurrency/BankTellerSimulation.java
Normal file
212
src/concurrency/BankTellerSimulation.java
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
package concurrency;//: concurrency/BankTellerSimulation.java
|
||||||
|
// Using queues and multithreading.
|
||||||
|
// {Args: 5}
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
// Read-only objects don't require synchronization:
|
||||||
|
class Customer {
|
||||||
|
private final int serviceTime;
|
||||||
|
public Customer(int tm) { serviceTime = tm; }
|
||||||
|
public int getServiceTime() { return serviceTime; }
|
||||||
|
public String toString() {
|
||||||
|
return "[" + serviceTime + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teach the customer line to display itself:
|
||||||
|
class CustomerLine extends ArrayBlockingQueue<Customer> {
|
||||||
|
public CustomerLine(int maxLineSize) {
|
||||||
|
super(maxLineSize);
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
if(this.size() == 0) {
|
||||||
|
return "[Empty]";
|
||||||
|
}
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for(Customer customer : this) {
|
||||||
|
result.append(customer);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly add customers to a queue:
|
||||||
|
class CustomerGenerator implements Runnable {
|
||||||
|
private CustomerLine customers;
|
||||||
|
private static Random rand = new Random(47);
|
||||||
|
public CustomerGenerator(CustomerLine cq) {
|
||||||
|
customers = cq;
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while(!Thread.interrupted()) {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(rand.nextInt(300));
|
||||||
|
customers.put(new Customer(rand.nextInt(1000)));
|
||||||
|
}
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
System.out.println("CustomerGenerator interrupted");
|
||||||
|
}
|
||||||
|
System.out.println("CustomerGenerator terminating");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Teller implements Runnable, Comparable<Teller> {
|
||||||
|
private static int counter = 0;
|
||||||
|
private final int id = counter++;
|
||||||
|
// Customers served during this shift:
|
||||||
|
private int customersServed = 0;
|
||||||
|
private CustomerLine customers;
|
||||||
|
private boolean servingCustomerLine = true;
|
||||||
|
public Teller(CustomerLine cq) { customers = cq; }
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while(!Thread.interrupted()) {
|
||||||
|
Customer customer = customers.take();
|
||||||
|
TimeUnit.MILLISECONDS.sleep(
|
||||||
|
customer.getServiceTime());
|
||||||
|
synchronized(this) {
|
||||||
|
customersServed++;
|
||||||
|
while(!servingCustomerLine) {
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
System.out.println(this + "interrupted");
|
||||||
|
}
|
||||||
|
System.out.println(this + "terminating");
|
||||||
|
}
|
||||||
|
public synchronized void doSomethingElse() {
|
||||||
|
customersServed = 0;
|
||||||
|
servingCustomerLine = false;
|
||||||
|
}
|
||||||
|
public synchronized void serveCustomerLine() {
|
||||||
|
assert !servingCustomerLine:"already serving: " + this;
|
||||||
|
servingCustomerLine = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
public String toString() { return "Teller " + id + " "; }
|
||||||
|
public String shortString() { return "T" + id; }
|
||||||
|
// Used by priority queue:
|
||||||
|
public synchronized int compareTo(Teller other) {
|
||||||
|
return customersServed < other.customersServed ? -1 :
|
||||||
|
(customersServed == other.customersServed ? 0 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TellerManager implements Runnable {
|
||||||
|
private ExecutorService exec;
|
||||||
|
private CustomerLine customers;
|
||||||
|
private PriorityQueue<Teller> workingTellers =
|
||||||
|
new PriorityQueue<Teller>();
|
||||||
|
private Queue<Teller> tellersDoingOtherThings =
|
||||||
|
new LinkedList<Teller>();
|
||||||
|
private int adjustmentPeriod;
|
||||||
|
private static Random rand = new Random(47);
|
||||||
|
public TellerManager(ExecutorService e,
|
||||||
|
CustomerLine customers, int adjustmentPeriod) {
|
||||||
|
exec = e;
|
||||||
|
this.customers = customers;
|
||||||
|
this.adjustmentPeriod = adjustmentPeriod;
|
||||||
|
// Start with a single teller:
|
||||||
|
Teller teller = new Teller(customers);
|
||||||
|
exec.execute(teller);
|
||||||
|
workingTellers.add(teller);
|
||||||
|
}
|
||||||
|
public void adjustTellerNumber() {
|
||||||
|
// This is actually a control system. By adjusting
|
||||||
|
// the numbers, you can reveal stability issues in
|
||||||
|
// the control mechanism.
|
||||||
|
// If line is too long, add another teller:
|
||||||
|
if(customers.size() / workingTellers.size() > 2) {
|
||||||
|
// If tellers are on break or doing
|
||||||
|
// another job, bring one back:
|
||||||
|
if(tellersDoingOtherThings.size() > 0) {
|
||||||
|
Teller teller = tellersDoingOtherThings.remove();
|
||||||
|
teller.serveCustomerLine();
|
||||||
|
workingTellers.offer(teller);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Else create (hire) a new teller
|
||||||
|
Teller teller = new Teller(customers);
|
||||||
|
exec.execute(teller);
|
||||||
|
workingTellers.add(teller);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If line is short enough, remove a teller:
|
||||||
|
if(workingTellers.size() > 1 &&
|
||||||
|
customers.size() / workingTellers.size() < 2) {
|
||||||
|
reassignOneTeller();
|
||||||
|
}
|
||||||
|
// If there is no line, we only need one teller:
|
||||||
|
if(customers.size() == 0) {
|
||||||
|
while(workingTellers.size() > 1) {
|
||||||
|
reassignOneTeller();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Give a teller a different job or a break:
|
||||||
|
private void reassignOneTeller() {
|
||||||
|
Teller teller = workingTellers.poll();
|
||||||
|
teller.doSomethingElse();
|
||||||
|
tellersDoingOtherThings.offer(teller);
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while(!Thread.interrupted()) {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(adjustmentPeriod);
|
||||||
|
adjustTellerNumber();
|
||||||
|
System.out.print(customers + " { ");
|
||||||
|
for(Teller teller : workingTellers) {
|
||||||
|
System.out.print(teller.shortString() + " ");
|
||||||
|
}
|
||||||
|
System.out.println("}");
|
||||||
|
}
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
System.out.println(this + "interrupted");
|
||||||
|
}
|
||||||
|
System.out.println(this + "terminating");
|
||||||
|
}
|
||||||
|
public String toString() { return "TellerManager "; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BankTellerSimulation {
|
||||||
|
static final int MAX_LINE_SIZE = 50;
|
||||||
|
static final int ADJUSTMENT_PERIOD = 1000;
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ExecutorService exec = Executors.newCachedThreadPool();
|
||||||
|
// If line is too long, customers will leave:
|
||||||
|
CustomerLine customers =
|
||||||
|
new CustomerLine(MAX_LINE_SIZE);
|
||||||
|
exec.execute(new CustomerGenerator(customers));
|
||||||
|
// Manager will add and remove tellers as necessary:
|
||||||
|
exec.execute(new TellerManager(
|
||||||
|
exec, customers, ADJUSTMENT_PERIOD));
|
||||||
|
if(args.length > 0) // Optional argument
|
||||||
|
{
|
||||||
|
TimeUnit.SECONDS.sleep(new Integer(args[0]));
|
||||||
|
} else {
|
||||||
|
System.out.println("Press 'Enter' to quit");
|
||||||
|
System.in.read();
|
||||||
|
}
|
||||||
|
exec.shutdownNow();
|
||||||
|
}
|
||||||
|
} /* Output: (Sample)
|
||||||
|
[429][200][207] { T0 T1 }
|
||||||
|
[861][258][140][322] { T0 T1 }
|
||||||
|
[575][342][804][826][896][984] { T0 T1 T2 }
|
||||||
|
[984][810][141][12][689][992][976][368][395][354] { T0 T1 T2 T3 }
|
||||||
|
Teller 2 interrupted
|
||||||
|
Teller 2 terminating
|
||||||
|
Teller 1 interrupted
|
||||||
|
Teller 1 terminating
|
||||||
|
TellerManager interrupted
|
||||||
|
TellerManager terminating
|
||||||
|
Teller 3 interrupted
|
||||||
|
Teller 3 terminating
|
||||||
|
Teller 0 interrupted
|
||||||
|
Teller 0 terminating
|
||||||
|
CustomerGenerator interrupted
|
||||||
|
CustomerGenerator terminating
|
||||||
|
*///:~
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user