SlideShare uma empresa Scribd logo
1 de 87
Baixar para ler offline
Active Software Documentation
using
Soul and IntensiVE
Johan Brichau, Kim Mens,
Coen De Roover, Andy Kellens,
Roel Wuyts

Département d’Ingénierie Informatique - Université catholique de Louvain

Monday 30 March 2009
Documenting Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}
public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

}
public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

2
Documenting Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}
public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

}
public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

Calls to database

2
Documenting Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

(open + (read/write) + close)

Factory Methods
- Must be used to create
objects consistently

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

- After state change
- Follows DB protocol

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

Calls to database

2
Documenting Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

Calls to database

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

2
Documenting Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

Discovering and
Documenting
Regularities
Architecture
Idioms
Patterns
Conventions
public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

Bugs
Bad smells

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

Calls to database

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

2
Evolving Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

*/

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

public void run()
{

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

Calls to database

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

3
Evolving Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public class HappyNewYear implements Runnable
private
private
private
private
private

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

*/

}
public void run()
{

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

}

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
);
frame.setUndecorated(true);
JLabel label = new JLabel("."); label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");

*/

Calls to database

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

}

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

3
Evolving Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

?

public class HappyNewYear implements Runnable
private
private
private
private
private

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

*/

}
public void run()
{

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

}

}

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
);
frame.setUndecorated(true);
JLabel label = new JLabel("."); label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");

*/

Calls to database

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

3
Evolving Software...
Software Documentation

import java.io.*;
import java.util.zip.*;
/**
* Command line program to copy a file to another directory.
* @author Marco Schmidt
*/
public class CopyFile {

// constant values for the override option

public static final int OVERWRITE_ALWAYS = 1;

public static final int OVERWRITE_NEVER = 2;

public static final int OVERWRITE_ASK = 3;







// program options initialized to default values
private static int bufferSize = 4 * 1024;
private static boolean clock = true;
private static boolean copyOriginalTimestamp = true;
private static boolean verify = true;
private static int override = OVERWRITE_ASK;
































public static Long copyFile(File srcFile, File destFile)

throws IOException {

InputStream in = new FileInputStream(srcFile);

OutputStream out = new FileOutputStream(destFile);

long millis = System.currentTimeMillis();

CRC32 checksum = null;

if (verify) {


checksum = new CRC32();


checksum.reset();

}

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


if (verify) {



checksum.update(buffer, 0, bytesRead);


}


out.write(buffer, 0, bytesRead);

}

out.close();

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

if (verify) {


return new Long(checksum.getValue());

} else {


return null;

}
}



















public static Long createChecksum(File file) throws IOException {

long millis = System.currentTimeMillis();

InputStream in = new FileInputStream(file);

CRC32 checksum = new CRC32();

checksum.reset();

byte[] buffer = new byte[bufferSize];

int bytesRead;

while ((bytesRead = in.read(buffer)) >= 0) {


checksum.update(buffer, 0, bytesRead);

}

in.close();

if (clock) {


millis = System.currentTimeMillis() - millis;


System.out.println("Second(s): " + (millis/1000L));

}

return new Long(checksum.getValue());
}

























/**
* Determine if data is to be copied to given file.
* Take into consideration override option and
* ask user in case file exists and override option is ask.
* @param file File object for potential destination file
* @return true if data is to be copied to file, false if not
*/
public static boolean doCopy(File file) {

boolean exists = file.exists();

if (override == OVERWRITE_ALWAYS || !exists) {


return true;

} else

if (override == OVERWRITE_NEVER) {


return false;

} else

if (override == OVERWRITE_ASK) {


return readYesNoFromStandardInput("File exists. " +



"Overwrite (y/n)?");

} else {


throw new InternalError("Program error. Invalid " +



"value for override: " + override);

}
}






















public static void main(String[] args) throws IOException {

// make sure there are exactly two arguments

if (args.length != 2) {


System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME");


System.exit(1);

}

// make sure the source file is indeed a readable file

File srcFile = new File(args[0]);

if (!srcFile.isFile() || !srcFile.canRead()) {


System.err.println("Not a readable file: " + srcFile.getName());


System.exit(1);

}

// make sure the second argument is a directory

File destDir = new File(args[1]);

if (!destDir.isDirectory()) {


System.err.println("Not a directory: " + destDir.getName());


System.exit(1);

}

// create File object for destination file

File destFile = new File(destDir, srcFile.getName());











// check if copying is desired given overwrite option
if (!doCopy(destFile)) {

return;
}







// copy file, optionally creating a checksum
Long checksumSrc = copyFile(srcFile, destFile);

















// copy timestamp of last modification
if (copyOriginalTimestamp) {

if (!destFile.setLastModified(srcFile.lastModified())) {


System.err.println("Error: Could not set " +



"timestamp of copied file.");

}
}























}

// optionally verify file
if (verify) {

System.out.print("Verifying destination file...");

Long checksumDest = createChecksum(destFile);

if (checksumSrc.equals(checksumDest)) {


System.out.println(" OK, files are equal.");

} else {


System.out.println(" Error: Checksums differ.");

}
}












































}

*/
public class FileDownload {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(
new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "t" + numWritten);
} catch (Exception exception) {
exception.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioe) {
}
}
}

/**
* Print a message to standard output and read lines from
* standard input until yes or no (y or n) is entered.
* @param message informative text to be answered by user
* @return user answer, true for yes, false for no.
*/
public static boolean readYesNoFromStandardInput(String message) {

System.out.println(message);

String line;

BufferedReader in = new BufferedReader(new InputStreamReader(


System.in));

Boolean answer = null;

try

{


while ((line = in.readLine()) != null) {



line = line.toLowerCase();



if ("y".equals(line) || "yes".equals(line)) {




answer = Boolean.TRUE;




break;



}



else



if ("n".equals(line) || "no".equals(line)) {




answer = Boolean.FALSE;




break;



}



else



{




System.out.println("Could not understand answer ("" +





line + ""). Please use y for yes or n for no.");



}


}


if (answer == null) {



throw new IOException("Unexpected end of input from stdin.");


}


in.close();


return answer.booleanValue();

}

catch (IOException ioe)

{


throw new InternalError(



"Cannot read from stdin or write to stdout.");

}
}

public class HappyNewYear implements Runnable
private
private
private
private
private

public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, address.substring(lastSlashIndex + 1));
} else {
System.err.println("Could not figure out local file name for " +
address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}

}

public class HappyNewYear implements Runnable
private
private
private
private
private

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}

*/

}
public void run()
{

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

}

}

- After state change
- Follows DB protocol
(open + (read/write) + close)

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public HappyNewYear(JFrame frame, JLabel label)
{
// store argument GUI elements
this.frame = frame;
this.label = label;
// compute beginning of next year
Calendar cal = new GregorianCalendar();
int nextYear = cal.get(Calendar.YEAR) + 1;
cal.set(Calendar.YEAR, nextYear);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
newYearMillis = cal.getTime().getTime();
// prepare a message
message = "Happy " + nextYear + "!";
}

{
static NumberFormat formatter = NumberFormat.getInstance();
JFrame frame;
JLabel label;
long newYearMillis;
String message;

public static int determineFontSize(JFrame frame,
int componentWidth, String fontName, int fontStyle,
String text)
{
int fontSize = componentWidth * 2 / text.length();
Font font = new Font(fontName, fontStyle, fontSize);
FontMetrics fontMetrics = frame.getGraphics().
getFontMetrics(font);
int stringWidth = fontMetrics.stringWidth(text);
return (int)(fontSize * 0.95 *
componentWidth / stringWidth);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
);
frame.setUndecorated(true);
JLabel label = new JLabel("."); label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");

*/

Calls to database

public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent event) {}
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ESCAPE)
{
System.exit(0);
}
}
public void keyTyped(KeyEvent event) {}
}
);
frame.setUndecorated(true);
JLabel label = new JLabel(".");
label.setBackground(Color.BLACK);
label.setForeground(Color.WHITE);
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(label);
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().setFullScreenWindow(frame);
final int fontStyle = Font.BOLD;
final String fontName = "SansSerif";
int fontSizeNumber = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, formatter.format(88888888));
int fontSizeText = determineFontSize(frame,
Toolkit.getDefaultToolkit().getScreenSize().width,
fontName, fontStyle, "Happy 8888!");
label.setFont(new Font(fontName, fontStyle,
Math.min(fontSizeNumber, fontSizeText)));
new HappyNewYear(frame, label).run();

boolean newYear = false;
do
{
long time = System.currentTimeMillis();
long remaining = (newYearMillis - time) / 1000L;
String output;
if (remaining < 1)
{
// new year!
newYear = true;
output = message;
}
else
{
// make a String from the number of seconds
output = formatter.format(remaining);
}
label.setText(output);
try
{
Thread.sleep(1000);

Factory Methods
- Must be used to create
objects consistently

Coding Convention
- Classes implementing
events: ‘*Event’
- Must be adhered for
consistency

}

Active Software Documentation using Logic Metaprogramming
Monday 30 March 2009

4
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE
Active Software Documentation using Soul and IntensiVE

Mais conteúdo relacionado

Mais procurados

Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Flink Forward
 
Apache Flink Training: DataSet API Basics
Apache Flink Training: DataSet API BasicsApache Flink Training: DataSet API Basics
Apache Flink Training: DataSet API BasicsFlink Forward
 
FlashAir Android App Development
FlashAir Android App DevelopmentFlashAir Android App Development
FlashAir Android App DevelopmentFlashAir Developers
 
Core java pract_sem iii
Core java pract_sem iiiCore java pract_sem iii
Core java pract_sem iiiNiraj Bharambe
 
Java practice programs for beginners
Java practice programs for beginnersJava practice programs for beginners
Java practice programs for beginnersishan0019
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196Mahmoud Samir Fayed
 
JDK1.7 features
JDK1.7 featuresJDK1.7 features
JDK1.7 featuresindia_mani
 
Non blocking io with netty
Non blocking io with nettyNon blocking io with netty
Non blocking io with nettyZauber
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Kiyotaka Oku
 
Java 7 Features and Enhancements
Java 7 Features and EnhancementsJava 7 Features and Enhancements
Java 7 Features and EnhancementsGagan Agrawal
 
разработка серверов и серверных приложений лекция №4
разработка серверов и серверных приложений лекция №4разработка серверов и серверных приложений лекция №4
разработка серверов и серверных приложений лекция №4Eugeniy Tyumentcev
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 

Mais procurados (19)

Thread
ThreadThread
Thread
 
Crawler 2
Crawler 2Crawler 2
Crawler 2
 
Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced Apache Flink Training: DataStream API Part 2 Advanced
Apache Flink Training: DataStream API Part 2 Advanced
 
Apache Flink Training: DataSet API Basics
Apache Flink Training: DataSet API BasicsApache Flink Training: DataSet API Basics
Apache Flink Training: DataSet API Basics
 
DCN Practical
DCN PracticalDCN Practical
DCN Practical
 
FlashAir Android App Development
FlashAir Android App DevelopmentFlashAir Android App Development
FlashAir Android App Development
 
Core java pract_sem iii
Core java pract_sem iiiCore java pract_sem iii
Core java pract_sem iii
 
4 gouping object
4 gouping object4 gouping object
4 gouping object
 
Socket Programming
Socket ProgrammingSocket Programming
Socket Programming
 
Java practice programs for beginners
Java practice programs for beginnersJava practice programs for beginners
Java practice programs for beginners
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196
 
Lab4
Lab4Lab4
Lab4
 
JDK1.7 features
JDK1.7 featuresJDK1.7 features
JDK1.7 features
 
Non blocking io with netty
Non blocking io with nettyNon blocking io with netty
Non blocking io with netty
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介
 
Java 7 Features and Enhancements
Java 7 Features and EnhancementsJava 7 Features and Enhancements
Java 7 Features and Enhancements
 
разработка серверов и серверных приложений лекция №4
разработка серверов и серверных приложений лекция №4разработка серверов и серверных приложений лекция №4
разработка серверов и серверных приложений лекция №4
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 

Destaque

Mining source code for structural regularities (SATTOSE2010)
Mining source code for structural regularities (SATTOSE2010)Mining source code for structural regularities (SATTOSE2010)
Mining source code for structural regularities (SATTOSE2010)kim.mens
 
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...kim.mens
 
From SOA to SCA and FraSCAti
From SOA to SCA and FraSCAtiFrom SOA to SCA and FraSCAti
From SOA to SCA and FraSCAtiphilippe_merle
 
Bad Code Smells
Bad Code SmellsBad Code Smells
Bad Code Smellskim.mens
 
Software Reuse and Object-Oriented Programming
Software Reuse and Object-Oriented ProgrammingSoftware Reuse and Object-Oriented Programming
Software Reuse and Object-Oriented Programmingkim.mens
 
Software Maintenance and Evolution
Software Maintenance and EvolutionSoftware Maintenance and Evolution
Software Maintenance and Evolutionkim.mens
 

Destaque (6)

Mining source code for structural regularities (SATTOSE2010)
Mining source code for structural regularities (SATTOSE2010)Mining source code for structural regularities (SATTOSE2010)
Mining source code for structural regularities (SATTOSE2010)
 
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...
IntensiVE - A Toolsuite For Documenting and Checking Structural Source-Code R...
 
From SOA to SCA and FraSCAti
From SOA to SCA and FraSCAtiFrom SOA to SCA and FraSCAti
From SOA to SCA and FraSCAti
 
Bad Code Smells
Bad Code SmellsBad Code Smells
Bad Code Smells
 
Software Reuse and Object-Oriented Programming
Software Reuse and Object-Oriented ProgrammingSoftware Reuse and Object-Oriented Programming
Software Reuse and Object-Oriented Programming
 
Software Maintenance and Evolution
Software Maintenance and EvolutionSoftware Maintenance and Evolution
Software Maintenance and Evolution
 

Semelhante a Active Software Documentation using Soul and IntensiVE

5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системеDEVTYPE
 
Android Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdfAndroid Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdffeelinggift
 
Java programming lab_manual_by_rohit_jaiswar
Java programming lab_manual_by_rohit_jaiswarJava programming lab_manual_by_rohit_jaiswar
Java programming lab_manual_by_rohit_jaiswarROHIT JAISWAR
 
I can not get my code to comply it gets mad that I have run declare mo.docx
I can not get my code to comply it gets mad that I have run declare mo.docxI can not get my code to comply it gets mad that I have run declare mo.docx
I can not get my code to comply it gets mad that I have run declare mo.docxhamblymarta
 
Understanding java streams
Understanding java streamsUnderstanding java streams
Understanding java streamsShahjahan Samoon
 
source code which create file and write into it
source code which create file and write into itsource code which create file and write into it
source code which create file and write into itmelakusisay507
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIjagriti srivastava
 
Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartGabriele Lana
 
Exmaples of file handling
Exmaples of file handlingExmaples of file handling
Exmaples of file handlingsparkishpearl
 
Java Programming Must implement a storage manager that main.pdf
Java Programming Must implement a storage manager that main.pdfJava Programming Must implement a storage manager that main.pdf
Java Programming Must implement a storage manager that main.pdfadinathassociates
 
Create a text file named lnfo.txt. Enter the following informatio.pdf
Create a text file named lnfo.txt. Enter the following informatio.pdfCreate a text file named lnfo.txt. Enter the following informatio.pdf
Create a text file named lnfo.txt. Enter the following informatio.pdfshahidqamar17
 
자바스터디 4
자바스터디 4자바스터디 4
자바스터디 4jangpd007
 

Semelhante a Active Software Documentation using Soul and IntensiVE (20)

5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе
 
Android Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdfAndroid Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdf
 
JavaExamples
JavaExamplesJavaExamples
JavaExamples
 
Java programming lab_manual_by_rohit_jaiswar
Java programming lab_manual_by_rohit_jaiswarJava programming lab_manual_by_rohit_jaiswar
Java programming lab_manual_by_rohit_jaiswar
 
Inheritance
InheritanceInheritance
Inheritance
 
Oop lecture9 11
Oop lecture9 11Oop lecture9 11
Oop lecture9 11
 
I can not get my code to comply it gets mad that I have run declare mo.docx
I can not get my code to comply it gets mad that I have run declare mo.docxI can not get my code to comply it gets mad that I have run declare mo.docx
I can not get my code to comply it gets mad that I have run declare mo.docx
 
Understanding java streams
Understanding java streamsUnderstanding java streams
Understanding java streams
 
source code which create file and write into it
source code which create file and write into itsource code which create file and write into it
source code which create file and write into it
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Code red SUM
Code red SUMCode red SUM
Code red SUM
 
Bhaloo
BhalooBhaloo
Bhaloo
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
 
Refactoring In Tdd The Missing Part
Refactoring In Tdd The Missing PartRefactoring In Tdd The Missing Part
Refactoring In Tdd The Missing Part
 
Java 7
Java 7Java 7
Java 7
 
Exmaples of file handling
Exmaples of file handlingExmaples of file handling
Exmaples of file handling
 
Oop lecture9 12
Oop lecture9 12Oop lecture9 12
Oop lecture9 12
 
Java Programming Must implement a storage manager that main.pdf
Java Programming Must implement a storage manager that main.pdfJava Programming Must implement a storage manager that main.pdf
Java Programming Must implement a storage manager that main.pdf
 
Create a text file named lnfo.txt. Enter the following informatio.pdf
Create a text file named lnfo.txt. Enter the following informatio.pdfCreate a text file named lnfo.txt. Enter the following informatio.pdf
Create a text file named lnfo.txt. Enter the following informatio.pdf
 
자바스터디 4
자바스터디 4자바스터디 4
자바스터디 4
 

Mais de kim.mens

Context-Oriented Programming
Context-Oriented ProgrammingContext-Oriented Programming
Context-Oriented Programmingkim.mens
 
Object-Oriented Design Heuristics
Object-Oriented Design HeuristicsObject-Oriented Design Heuristics
Object-Oriented Design Heuristicskim.mens
 
Software Patterns
Software PatternsSoftware Patterns
Software Patternskim.mens
 
Code Refactoring
Code RefactoringCode Refactoring
Code Refactoringkim.mens
 
Domain Modelling
Domain ModellingDomain Modelling
Domain Modellingkim.mens
 
Object-Oriented Application Frameworks
Object-Oriented Application FrameworksObject-Oriented Application Frameworks
Object-Oriented Application Frameworkskim.mens
 
Towards a Context-Oriented Software Implementation Framework
Towards a Context-Oriented Software Implementation FrameworkTowards a Context-Oriented Software Implementation Framework
Towards a Context-Oriented Software Implementation Frameworkkim.mens
 
Towards a Taxonomy of Context-Aware Software Variabilty Approaches
Towards a Taxonomy of Context-Aware Software Variabilty ApproachesTowards a Taxonomy of Context-Aware Software Variabilty Approaches
Towards a Taxonomy of Context-Aware Software Variabilty Approacheskim.mens
 
Breaking the Walls: A Unified Vision on Context-Oriented Software Engineering
Breaking the Walls: A Unified Vision on Context-Oriented Software EngineeringBreaking the Walls: A Unified Vision on Context-Oriented Software Engineering
Breaking the Walls: A Unified Vision on Context-Oriented Software Engineeringkim.mens
 
Context-oriented programming
Context-oriented programmingContext-oriented programming
Context-oriented programmingkim.mens
 
Basics of reflection
Basics of reflectionBasics of reflection
Basics of reflectionkim.mens
 
Advanced Reflection in Java
Advanced Reflection in JavaAdvanced Reflection in Java
Advanced Reflection in Javakim.mens
 
Basics of reflection in java
Basics of reflection in javaBasics of reflection in java
Basics of reflection in javakim.mens
 
Reflection in Ruby
Reflection in RubyReflection in Ruby
Reflection in Rubykim.mens
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Rubykim.mens
 
Introduction to Smalltalk
Introduction to SmalltalkIntroduction to Smalltalk
Introduction to Smalltalkkim.mens
 
A gentle introduction to reflection
A gentle introduction to reflectionA gentle introduction to reflection
A gentle introduction to reflectionkim.mens
 
Managing the Evolution of Information Systems with Intensional Views and Rela...
Managing the Evolution of Information Systems with Intensional Views and Rela...Managing the Evolution of Information Systems with Intensional Views and Rela...
Managing the Evolution of Information Systems with Intensional Views and Rela...kim.mens
 
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)kim.mens
 
Usage contracts in a nutshell
Usage contracts in a nutshellUsage contracts in a nutshell
Usage contracts in a nutshellkim.mens
 

Mais de kim.mens (20)

Context-Oriented Programming
Context-Oriented ProgrammingContext-Oriented Programming
Context-Oriented Programming
 
Object-Oriented Design Heuristics
Object-Oriented Design HeuristicsObject-Oriented Design Heuristics
Object-Oriented Design Heuristics
 
Software Patterns
Software PatternsSoftware Patterns
Software Patterns
 
Code Refactoring
Code RefactoringCode Refactoring
Code Refactoring
 
Domain Modelling
Domain ModellingDomain Modelling
Domain Modelling
 
Object-Oriented Application Frameworks
Object-Oriented Application FrameworksObject-Oriented Application Frameworks
Object-Oriented Application Frameworks
 
Towards a Context-Oriented Software Implementation Framework
Towards a Context-Oriented Software Implementation FrameworkTowards a Context-Oriented Software Implementation Framework
Towards a Context-Oriented Software Implementation Framework
 
Towards a Taxonomy of Context-Aware Software Variabilty Approaches
Towards a Taxonomy of Context-Aware Software Variabilty ApproachesTowards a Taxonomy of Context-Aware Software Variabilty Approaches
Towards a Taxonomy of Context-Aware Software Variabilty Approaches
 
Breaking the Walls: A Unified Vision on Context-Oriented Software Engineering
Breaking the Walls: A Unified Vision on Context-Oriented Software EngineeringBreaking the Walls: A Unified Vision on Context-Oriented Software Engineering
Breaking the Walls: A Unified Vision on Context-Oriented Software Engineering
 
Context-oriented programming
Context-oriented programmingContext-oriented programming
Context-oriented programming
 
Basics of reflection
Basics of reflectionBasics of reflection
Basics of reflection
 
Advanced Reflection in Java
Advanced Reflection in JavaAdvanced Reflection in Java
Advanced Reflection in Java
 
Basics of reflection in java
Basics of reflection in javaBasics of reflection in java
Basics of reflection in java
 
Reflection in Ruby
Reflection in RubyReflection in Ruby
Reflection in Ruby
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
Introduction to Smalltalk
Introduction to SmalltalkIntroduction to Smalltalk
Introduction to Smalltalk
 
A gentle introduction to reflection
A gentle introduction to reflectionA gentle introduction to reflection
A gentle introduction to reflection
 
Managing the Evolution of Information Systems with Intensional Views and Rela...
Managing the Evolution of Information Systems with Intensional Views and Rela...Managing the Evolution of Information Systems with Intensional Views and Rela...
Managing the Evolution of Information Systems with Intensional Views and Rela...
 
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)
Usage contracts (presented at SATToSE 2014 in L'Aquila, Italy)
 
Usage contracts in a nutshell
Usage contracts in a nutshellUsage contracts in a nutshell
Usage contracts in a nutshell
 

Último

[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 

Último (20)

[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 

Active Software Documentation using Soul and IntensiVE

  • 1. Active Software Documentation using Soul and IntensiVE Johan Brichau, Kim Mens, Coen De Roover, Andy Kellens, Roel Wuyts Département d’Ingénierie Informatique - Université catholique de Louvain Monday 30 March 2009
  • 2. Documenting Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 2
  • 3. Documenting Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 Calls to database 2
  • 4. Documenting Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); (open + (read/write) + close) Factory Methods - Must be used to create objects consistently boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 - After state change - Follows DB protocol { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } Calls to database 2
  • 5. Documenting Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } Calls to database Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency 2
  • 6. Documenting Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } Discovering and Documenting Regularities Architecture Idioms Patterns Conventions public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); Bugs Bad smells boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } Calls to database Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency 2
  • 7. Evolving Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private */ public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public void run() { } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } Calls to database Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency 3
  • 8. Evolving Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public class HappyNewYear implements Runnable private private private private private public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } */ } public void run() { public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } } - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); */ Calls to database public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency } Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 3
  • 9. Evolving Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } ? public class HappyNewYear implements Runnable private private private private private public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } */ } public void run() { public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } } } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); */ Calls to database Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency 3
  • 10. Evolving Software... Software Documentation import java.io.*; import java.util.zip.*; /** * Command line program to copy a file to another directory. * @author Marco Schmidt */ public class CopyFile { // constant values for the override option public static final int OVERWRITE_ALWAYS = 1; public static final int OVERWRITE_NEVER = 2; public static final int OVERWRITE_ASK = 3; // program options initialized to default values private static int bufferSize = 4 * 1024; private static boolean clock = true; private static boolean copyOriginalTimestamp = true; private static boolean verify = true; private static int override = OVERWRITE_ASK; public static Long copyFile(File srcFile, File destFile) throws IOException { InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(destFile); long millis = System.currentTimeMillis(); CRC32 checksum = null; if (verify) { checksum = new CRC32(); checksum.reset(); } byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { if (verify) { checksum.update(buffer, 0, bytesRead); } out.write(buffer, 0, bytesRead); } out.close(); in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } if (verify) { return new Long(checksum.getValue()); } else { return null; } } public static Long createChecksum(File file) throws IOException { long millis = System.currentTimeMillis(); InputStream in = new FileInputStream(file); CRC32 checksum = new CRC32(); checksum.reset(); byte[] buffer = new byte[bufferSize]; int bytesRead; while ((bytesRead = in.read(buffer)) >= 0) { checksum.update(buffer, 0, bytesRead); } in.close(); if (clock) { millis = System.currentTimeMillis() - millis; System.out.println("Second(s): " + (millis/1000L)); } return new Long(checksum.getValue()); } /** * Determine if data is to be copied to given file. * Take into consideration override option and * ask user in case file exists and override option is ask. * @param file File object for potential destination file * @return true if data is to be copied to file, false if not */ public static boolean doCopy(File file) { boolean exists = file.exists(); if (override == OVERWRITE_ALWAYS || !exists) { return true; } else if (override == OVERWRITE_NEVER) { return false; } else if (override == OVERWRITE_ASK) { return readYesNoFromStandardInput("File exists. " + "Overwrite (y/n)?"); } else { throw new InternalError("Program error. Invalid " + "value for override: " + override); } } public static void main(String[] args) throws IOException { // make sure there are exactly two arguments if (args.length != 2) { System.err.println("Usage: CopyFile SRC-FILE-NAME DEST-DIR-NAME"); System.exit(1); } // make sure the source file is indeed a readable file File srcFile = new File(args[0]); if (!srcFile.isFile() || !srcFile.canRead()) { System.err.println("Not a readable file: " + srcFile.getName()); System.exit(1); } // make sure the second argument is a directory File destDir = new File(args[1]); if (!destDir.isDirectory()) { System.err.println("Not a directory: " + destDir.getName()); System.exit(1); } // create File object for destination file File destFile = new File(destDir, srcFile.getName()); // check if copying is desired given overwrite option if (!doCopy(destFile)) { return; } // copy file, optionally creating a checksum Long checksumSrc = copyFile(srcFile, destFile); // copy timestamp of last modification if (copyOriginalTimestamp) { if (!destFile.setLastModified(srcFile.lastModified())) { System.err.println("Error: Could not set " + "timestamp of copied file."); } } } // optionally verify file if (verify) { System.out.print("Verifying destination file..."); Long checksumDest = createChecksum(destFile); if (checksumSrc.equals(checksumDest)) { System.out.println(" OK, files are equal."); } else { System.out.println(" Error: Checksums differ."); } } } */ public class FileDownload { public static void download(String address, String localFileName) { OutputStream out = null; URLConnection conn = null; InputStream in = null; try { URL url = new URL(address); out = new BufferedOutputStream( new FileOutputStream(localFileName)); conn = url.openConnection(); in = conn.getInputStream(); byte[] buffer = new byte[1024]; int numRead; long numWritten = 0; while ((numRead = in.read(buffer)) != -1) { out.write(buffer, 0, numRead); numWritten += numRead; } System.out.println(localFileName + "t" + numWritten); } catch (Exception exception) { exception.printStackTrace(); } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException ioe) { } } } /** * Print a message to standard output and read lines from * standard input until yes or no (y or n) is entered. * @param message informative text to be answered by user * @return user answer, true for yes, false for no. */ public static boolean readYesNoFromStandardInput(String message) { System.out.println(message); String line; BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); Boolean answer = null; try { while ((line = in.readLine()) != null) { line = line.toLowerCase(); if ("y".equals(line) || "yes".equals(line)) { answer = Boolean.TRUE; break; } else if ("n".equals(line) || "no".equals(line)) { answer = Boolean.FALSE; break; } else { System.out.println("Could not understand answer ("" + line + ""). Please use y for yes or n for no."); } } if (answer == null) { throw new IOException("Unexpected end of input from stdin."); } in.close(); return answer.booleanValue(); } catch (IOException ioe) { throw new InternalError( "Cannot read from stdin or write to stdout."); } } public class HappyNewYear implements Runnable private private private private private public static void download(String address) { int lastSlashIndex = address.lastIndexOf('/'); if (lastSlashIndex >= 0 && lastSlashIndex < address.length() - 1) { download(address, address.substring(lastSlashIndex + 1)); } else { System.err.println("Could not figure out local file name for " + address); } } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { download(args[i]); } } } public class HappyNewYear implements Runnable private private private private private public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } */ } public void run() { public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } } } - After state change - Follows DB protocol (open + (read/write) + close) { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public HappyNewYear(JFrame frame, JLabel label) { // store argument GUI elements this.frame = frame; this.label = label; // compute beginning of next year Calendar cal = new GregorianCalendar(); int nextYear = cal.get(Calendar.YEAR) + 1; cal.set(Calendar.YEAR, nextYear); cal.set(Calendar.MONTH, Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); newYearMillis = cal.getTime().getTime(); // prepare a message message = "Happy " + nextYear + "!"; } { static NumberFormat formatter = NumberFormat.getInstance(); JFrame frame; JLabel label; long newYearMillis; String message; public static int determineFontSize(JFrame frame, int componentWidth, String fontName, int fontStyle, String text) { int fontSize = componentWidth * 2 / text.length(); Font font = new Font(fontName, fontStyle, fontSize); FontMetrics fontMetrics = frame.getGraphics(). getFontMetrics(font); int stringWidth = fontMetrics.stringWidth(text); return (int)(fontSize * 0.95 * componentWidth / stringWidth); } public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); */ Calls to database public static void main(String[] args) { JFrame frame = new JFrame(); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent event) {} public void keyReleased(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { System.exit(0); } } public void keyTyped(KeyEvent event) {} } ); frame.setUndecorated(true); JLabel label = new JLabel("."); label.setBackground(Color.BLACK); label.setForeground(Color.WHITE); label.setOpaque(true); label.setHorizontalAlignment(SwingConstants.CENTER); frame.getContentPane().add(label); GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().setFullScreenWindow(frame); final int fontStyle = Font.BOLD; final String fontName = "SansSerif"; int fontSizeNumber = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, formatter.format(88888888)); int fontSizeText = determineFontSize(frame, Toolkit.getDefaultToolkit().getScreenSize().width, fontName, fontStyle, "Happy 8888!"); label.setFont(new Font(fontName, fontStyle, Math.min(fontSizeNumber, fontSizeText))); new HappyNewYear(frame, label).run(); boolean newYear = false; do { long time = System.currentTimeMillis(); long remaining = (newYearMillis - time) / 1000L; String output; if (remaining < 1) { // new year! newYear = true; output = message; } else { // make a String from the number of seconds output = formatter.format(remaining); } label.setText(output); try { Thread.sleep(1000); Factory Methods - Must be used to create objects consistently Coding Convention - Classes implementing events: ‘*Event’ - Must be adhered for consistency } Active Software Documentation using Logic Metaprogramming Monday 30 March 2009 4