/*******************************************************************************
* Copyright (C) 2003, 2004, 2007, 2008, 2013, Guillaume Brocker
* Copyright (C) 2015-2016, Andre Bossert
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Guillaume Brocker - Initial API and implementation
* Andre Bossert - Add ability to use Doxyfile not in project scope
*
******************************************************************************/
package eclox.core.doxyfiles;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import eclox.core.doxyfiles.io.Parser;
/**
* Implements the Doxyfile wrapper.
*
* @author gbrocker
*/
public class Doxyfile {
/**
* the eclipse file that holds the doxyfile content
*/
private IFile ifile;
/**
* the system file (outside eclipse) that holds the doxyfile content
*/
private File file;
/**
* a collection containing all doxyfile's chunks
*/
private AbstractList<Chunk> chunks = new Vector<Chunk>();
/**
* a map containing all managed settings
*/
private Map<String, Setting> settings = new LinkedHashMap<String, Setting>();
/**
* a map containing all managed groups
*/
private Map<String, Group> groups = new LinkedHashMap<String, Group>();
/**
* Tells if the given object is a doxyfile
*
* @param object an object to test
*
* @return true or false
*/
public static boolean isDoxyfile(Object object) {
return (object instanceof IResource) && isDoxyfile((IResource) object);
}
/**
* Tells if the specified resource is a doxyfile.
*
* @param resource the resource to test
*
* @return <code>true</code> or <code>false</code>
*/
public static boolean isDoxyfile(IResource resource) {
return (resource instanceof IFile) && isDoxyfile((IFile) resource);
}
/**
* Tells if the specified file is a doxyfile.
*
* @param file the file to test
*
* @return <code>true</code> or <code>false</code>
*/
public static boolean isDoxyfile(IFile file) {
String name = file.getName();
IContentType contentType = Platform.getContentTypeManager().findContentTypeFor( name );
return contentType != null ? contentType.getId().equals("org.gna.eclox.core.doxyfile") : false;
}
/**
* Constructor
*
* @param file a file resource instance that is assumed to be a doxyfile
*/
public Doxyfile( IFile ifile, File file ) {
this.ifile = ifile;
this.file = file;
}
public void load() throws CoreException, FileNotFoundException, IOException {
InputStream input;
if (ifile != null)
input = ifile.getContents();
else
input = new BufferedInputStream(new FileInputStream(file));
Parser parser = new Parser(input);
parser.read( this );
}
/**
* Appends a new chunk to the doxyfile.
*
* @param chunk a chunk to append to the doxyfile
*/
public void append( Chunk chunk ) {
// Pre-condition
assert chunk.getOwner() == null;
// References the chunk.
chunk.setOwner( this );
this.chunks.add( chunk );
// Do special handling for settings.
if( chunk instanceof Setting ) {
Setting setting = (Setting) chunk;
this.settings.put( setting.getIdentifier(), setting );
// Retrieves the setting group name.
String groupName = setting.getProperty( Setting.GROUP );
if( groupName == null ) {
groupName = new String( "Others" );
setting.setProperty( Setting.GROUP, groupName );
}
// Retrieves the setting group and stores the setting in it.
Group group = (Group) this.groups.get( groupName );
if( group == null ) {
group = new Group( groupName );
this.groups.put( groupName, group );
}
group.add( setting );
}
}
/**
* Retrieves the resource file that contains the doxyfile.
*
* @return a resource file
*/
public IFile getIFile() {
return ifile;
}
/**
* Retrieves the resource file that contains the doxyfile.
*
* @return a file
*/
public File getFile() {
return file;
}
/**
* Retrieves all groups present in the doxyfile.
*
* @return an array containing all groups
*/
public Object[] getGroups() {
return this.groups.values().toArray();
}
/**
* Retrieves the last appended chunk
*
* @return the last added chunk or null if none
*/
public Chunk getLastChunk() {
if( this.chunks.isEmpty() == false ) {
return (Chunk) this.chunks.get( this.chunks.size() - 1 );
}
else {
return null;
}
}
/**
* Retrieves the container that will receive the documentation build outputs.
*
* @return a folder, or null when none
*/
public IContainer getOutputContainer() {
IContainer outputContainer = null;
Setting outputSetting = getSetting("OUTPUT_DIRECTORY");
if(outputSetting != null) {
Path outputPath = new Path(outputSetting.getValue());
if(outputPath.isEmpty()) {
if (ifile != null) {
outputContainer = ifile.getParent();
}
} else {
File containerFile = null;
if(outputPath.isAbsolute()) {
containerFile = outputPath.toFile();
} else {
if (ifile != null) {
containerFile = ifile.getParent().getLocation().append(outputPath).toFile();
} else {
containerFile = new Path(file.getParentFile().getAbsolutePath()).append(outputPath).toFile();
}
}
if (containerFile != null && containerFile.exists()) {
IContainer[] foundContainers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(containerFile.toURI());
if (foundContainers.length >= 1) {
outputContainer = foundContainers[0];
}
}
}
}
return outputContainer;
}
/**
* Retrieves a single setting for the specified identifier.
*
* @param identifier a string containing a setting identifier
*
* @return the found setting or null if none
*/
public Setting getSetting( String identifier ) {
return (Setting) settings.get(identifier);
}
/**
* Retrieves all settings as an array
*
* @return an array of settings
*/
public Object[] getSettings() {
return settings.values().toArray();
}
/**
* Tells if the doxyfile has the given setting.
*
* @param identifier a string containing a setting identifier
*
* @return true or false
*/
public boolean hasSetting( String identifier ) {
return settings.get(identifier) != null;
}
/**
* Tells if the given path is relative to the doxyfile.
*
* @return true or false
*/
public boolean isPathRelative( IPath path ) {
if (ifile != null)
return ifile.getLocation().removeLastSegments(1).isPrefixOf( path );
else
return false;
}
/**
* Makes the given path relative to the doxyfile path only of the given
* path point to a location that is in the sub-directory containing the
* doxyfile.
*
* @return the argument path made relative to the doxyfile
*/
public IPath makePathRelative( IPath path ) {
if( isPathRelative(path) ) {
int matchingCount = ifile.getLocation().removeLastSegments(1).matchingFirstSegments( path );
IPath relativePath = path.removeFirstSegments( matchingCount ).setDevice( new String() );
return relativePath.isEmpty() ? new Path(".") : relativePath;
}
else {
return path;
}
}
/**
* Retrieves the iterator the whole chunk collection.
*
* @return an iterator on chunks
*/
public Iterator<Chunk> iterator() {
return this.chunks.iterator();
}
/**
* Retrieves the iterator on the setting collection.
*
* @return an iterator on Setting instances
*/
public Iterator<Setting> settingIterator() {
return settings.values().iterator();
}
public String getFullPath() {
if (ifile != null) {
return ifile.getFullPath().toOSString();
} else {
return file.getAbsolutePath();
}
}
public String getName() {
if (ifile != null) {
return ifile.getName();
} else {
return file.getName();
}
}
public boolean exists() {
if (ifile != null) {
return ifile.exists();
} else {
return file.exists();
}
}
}