Hallo Zusammen,
ich hoffe, da draussen ist jemand der mir helfen kann, da ich wohl "den Wald vor lauter Bäumen" leider nicht mehr sehe und quasi vollkommen auf dem Schlauch stehe ...
Und zwar geht es um Folgendes:
Ich möche einen Verzeichnisbaum unter Benutzung eines TreeViewers aufbauen. Dieser soll allerdings nicht wie in den oft erwähnten Tutorials von IBM (1, 2) seinen Content direkt aus den File-Objekten bekommen, sondern es soll eine Klassenhierarchie im Sinne des Composite-Entwurfsmusters benutzt werden.
Dazu habe ich folgende Klassen erstellt:
1) FileTreeItem als abstrakte Oberklasse für Files und Directories
2) DirectoryItem, repräsentiert ein Verzeichnis mit "Kind-Elementen" von Typ FileTreeItem
3) FileItem, repräsentiert Dateien ohne "Kind-Elemente"
Zusätzlich gibt es natürlich noch den ContentProvider sowie den LabelProvider, welche aber mit meinem Problem, oder besser Problemen nichts zu tun haben, glaub ich zumindestens, was aber nix heissen soll...
FileTreeContentProvider:
FileTreeLabelProvider:
Und der TreeViewer wird in meiner Applikation an folgender Stelle erstellt:
Soo, nun zu den Problemen, die bei meiner Implementierung auftreten. Ich habe für mich fragwürdige Stellen in den Quellen mit Fragezeichen markiert.
Mein Hauptproblem liegt wohl in der Klasse DirectoryItem und in der Methode createFolderContent(). Diese liest die File-Objekte eines angebenen Startverzeichnisses aus, erstellt für diese entsprechen DirectoryItem- bzw. FileItem-Objekte. Dieser Vorgang erfolgt rekursiv, wie man sieht wird die Methode im Konstruktor von DirectoryItem wieder aufgerufen und wandert somit die gesamte Verzeichnisstrukturs des Rechners entlang. Man kann sich denken, das dass natürlich immer erstmal EEEWIG dauert, was im Rahmen der Applikation nicht akzeptabel ist...
Meine Frage hierzu ist daher, wie ich Verzeichnisse anders aufbauen kann, ohne das von vornherein "Was-weiss-ich-wieviel"-Objekte erstellt werden
Eine weitere Sache die ich komisch finde, ist, das wenn ich wie im Quellcode angeben als Startverzeichnis "C:\\" angebe, ich, nach geraumer Zeit natürlich , eine NullPointerException in der createFolderContent()-Methode bekomme. Wenn ich aber z.B. "C:\\JavaLab" angebe, bekomme ich diese nicht...? Der Tree wird wunderbar dargestellt, nach Wartezeit....
Hier mal der StackTrace der Exception, Zeilennummern habe ich im Code eingefügt:
Und eine letzte Sache die ich nicht verstehe, ist der auskommentierte Teil am Schluss der createFolderContent()-Methode, wo das parentItem gesetzt werden soll. der ContentProvider ruft ja getParent() der Oberklasse FileTreeItem auf, die Variable parentItem wird aber gar nicht gesetzt. Trotzdem funktionierts, solange Verzeichnis nicht "C.\\" ist....
Ich weiss, das ist ganz schön viel auf einmal, doch ich hoffe das jemand meine Ratlosigkeit verstehen kann, und mir eventuell gedanklich ein wenig auf die Sprünge helfen kann. Die Themen JFace, sowie Entwurfsmuster sind komplettes Neuland für mich, was ich gerade sehr schmerzlich zu spüren bekomme...
Danke im Voraus und Gruß,
Jack
ich hoffe, da draussen ist jemand der mir helfen kann, da ich wohl "den Wald vor lauter Bäumen" leider nicht mehr sehe und quasi vollkommen auf dem Schlauch stehe ...
Und zwar geht es um Folgendes:
Ich möche einen Verzeichnisbaum unter Benutzung eines TreeViewers aufbauen. Dieser soll allerdings nicht wie in den oft erwähnten Tutorials von IBM (1, 2) seinen Content direkt aus den File-Objekten bekommen, sondern es soll eine Klassenhierarchie im Sinne des Composite-Entwurfsmusters benutzt werden.
Dazu habe ich folgende Klassen erstellt:
1) FileTreeItem als abstrakte Oberklasse für Files und Directories
Code:
public abstract class FileTreeItem
{
private String itemName;
private FileTreeItem parentItem;
private File file;
public FileTreeItem(final File file)
{
this.file = file;
setName(file.getName());
}
public abstract boolean hasChildren();
public abstract FileTreeItem[] getChildren();
public void setName(final String itemName) {
this.itemName = itemName;
}
public String getName() {
return itemName;
}
public FileTreeItem getParent() {
return parentItem;
}
public void setParent(final FileTreeItem parentItem) {
this.parentItem = parentItem;
}
public boolean isValidFile(final File file) {
return file.isFile() && file.exists() && file.canRead();
}
public boolean isValidDirectory(final File file) {
return file.isDirectory() && file.exists() && file.canRead();
}
public File getFile() {
return file;
}
}
Code:
public class DirectoryItem extends FileTreeItem
{
private ArrayList<FileTreeItem> children;
public DirectoryItem(final File file)
throws InvalidDirectoryException
{
super(file);
if(!isValidDirectory(file)) {
throw new InvalidDirectoryException("No valid directory:" + file.getPath());
}
children = new ArrayList<FileTreeItem>();
createFolderContent(); ? //ZEILE 49
}
public void addChild(final FileTreeItem child) {
children.add(child);
}
public FileTreeItem[] getChildren() {
return children.toArray(new FileTreeItem[children.size()]);
}
public boolean hasChildren() {
return children.size() > 0;
}
public void createFolderContent()
{
File[] folderContent = getFile().listFiles();
//System.out.print(folderContent.length);
for(int i=0; i<folderContent.length; i++) { //ZEILE 49
FileTreeItem newItem = null;
File newFile = folderContent[i];
if(isValidFile(newFile)) {
try {
newItem = new FileItem(newFile);
} catch(InvalidFileException ex) {
//ex.printStackTrace();
}
} else if(isValidDirectory(newFile)) {
try {
newItem = new DirectoryItem(newFile); //ZEILE 60
} catch (InvalidDirectoryException ex) {
//ex.printStackTrace();
}
}
if(newItem != null) {
/*
try {
newItem.setParent(new FileItem(newFile.getParentFile())); //?
} catch(Exception ex) {ex.printStackTrace(); }
*/
addChild(newItem);
}
}
}
}
Code:
public class FileItem extends FileTreeItem
{
public FileItem(final File file)
throws InvalidFileException
{
super(file);
if(!isValidDirectory(file)) {
throw new InvalidFileException("No valid file:" + file.getPath());
}
}
public boolean hasChildren() {
return false;
}
public FileTreeItem[] getChildren() {
return null;
}
}
FileTreeContentProvider:
Code:
public class FileTreeContentProvider implements ITreeContentProvider,
IStructuredContentProvider
{
public Object[] getChildren(Object parent) {
if(parent instanceof FileTreeItem) {
return ((FileTreeItem) parent).getChildren();
}
return new Object[0];
}
public Object getParent(Object child) {
if(child instanceof FileTreeItem) {
return ((FileTreeItem) child).getParent();
}
return null;
}
public boolean hasChildren(Object parent) {
if(parent instanceof FileTreeItem) {
return ((FileTreeItem) parent).hasChildren();
}
return false;
}
public Object[] getElements(Object parent) {
return getChildren(parent);
}
public void dispose() {
}
public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
}
}
FileTreeLabelProvider:
Code:
public class FileTreeLabelProvider implements ILabelProvider
{
public ImageCache cache = ImageCache.getInstance();
public Image getImage(Object arg0) {
if(arg0 instanceof FileItem) {
return cache.getImage("file");
} else {
return cache.getImage("folder");
}
}
public String getText(Object arg0) {
if(arg0 instanceof FileTreeItem) {
return ((FileTreeItem) arg0).getName();
}
return arg0.toString();
}
public void addListener(ILabelProviderListener arg0) {
}
public void dispose() {
}
public boolean isLabelProperty(Object arg0, String arg1) {
return false;
}
public void removeListener(ILabelProviderListener arg0) {
}
}
Und der TreeViewer wird in meiner Applikation an folgender Stelle erstellt:
Code:
....
FileTreeItem rootItem = null;
try {
rootItem = new DirectoryItem(new File("C:\\"));
} catch (InvalidDirectoryException ex) {
ex.printStackTrace();
}
TreeViewer tv = new TreeViewer(outerSash);
tv.setContentProvider(new FileTreeContentProvider());
tv.setLabelProvider(new FileTreeLabelProvider());
tv.setInput(rootItem);
...
Soo, nun zu den Problemen, die bei meiner Implementierung auftreten. Ich habe für mich fragwürdige Stellen in den Quellen mit Fragezeichen markiert.
Mein Hauptproblem liegt wohl in der Klasse DirectoryItem und in der Methode createFolderContent(). Diese liest die File-Objekte eines angebenen Startverzeichnisses aus, erstellt für diese entsprechen DirectoryItem- bzw. FileItem-Objekte. Dieser Vorgang erfolgt rekursiv, wie man sieht wird die Methode im Konstruktor von DirectoryItem wieder aufgerufen und wandert somit die gesamte Verzeichnisstrukturs des Rechners entlang. Man kann sich denken, das dass natürlich immer erstmal EEEWIG dauert, was im Rahmen der Applikation nicht akzeptabel ist...
Meine Frage hierzu ist daher, wie ich Verzeichnisse anders aufbauen kann, ohne das von vornherein "Was-weiss-ich-wieviel"-Objekte erstellt werden
Eine weitere Sache die ich komisch finde, ist, das wenn ich wie im Quellcode angeben als Startverzeichnis "C:\\" angebe, ich, nach geraumer Zeit natürlich , eine NullPointerException in der createFolderContent()-Methode bekomme. Wenn ich aber z.B. "C:\\JavaLab" angebe, bekomme ich diese nicht...? Der Tree wird wunderbar dargestellt, nach Wartezeit....
Hier mal der StackTrace der Exception, Zeilennummern habe ich im Code eingefügt:
Code:
Exception in thread "main" java.lang.NullPointerException
at xmlexplorer.tree.DirectoryItem.createFolderContent(DirectoryItem.java:49)
at xmlexplorer.tree.DirectoryItem.<init>(DirectoryItem.java:30)
at xmlexplorer.tree.DirectoryItem.createFolderContent(DirectoryItem.java:60)
at xmlexplorer.tree.DirectoryItem.<init>(DirectoryItem.java:30)
at xmlexplorer.XMLExplorer.createContents(XMLExplorer.java:106)
at org.eclipse.jface.window.Window.create(Window.java:418)
at org.eclipse.jface.window.Window.open(Window.java:776)
at xmlexplorer.XMLExplorer.run(XMLExplorer.java:93)
at xmlexplorer.GUI_Application.main(GUI_Application.java:50)
Ich weiss, das ist ganz schön viel auf einmal, doch ich hoffe das jemand meine Ratlosigkeit verstehen kann, und mir eventuell gedanklich ein wenig auf die Sprünge helfen kann. Die Themen JFace, sowie Entwurfsmuster sind komplettes Neuland für mich, was ich gerade sehr schmerzlich zu spüren bekomme...
Danke im Voraus und Gruß,
Jack