001 package nl.tudelft.tbm.eeni.owl2java.formatter;
002
003 import org.apache.commons.logging.Log;
004 import org.apache.commons.logging.LogFactory;
005 import org.eclipse.jdt.core.JavaCore;
006 import org.eclipse.jdt.core.ToolFactory;
007 import org.eclipse.jface.text.Document;
008 import org.eclipse.jface.text.IDocument;
009 import org.eclipse.text.edits.TextEdit;
010
011 import java.io.FileNotFoundException;
012 import java.io.IOException;
013 import java.io.InputStream;
014 import java.util.Properties;
015
016 /**
017 * Wrapper class for Eclipse JDT code formatter
018 */
019 public class CodeFormatter {
020 // Location of default settings file, relative to this class
021 private final static String DEFAULT_SETTINGS_FILE = "formatter-defaults.properties";
022
023 // Log message emitter
024 private static Log log = LogFactory.getLog(CodeFormattingWriter.class);
025
026 // Settings map for JDT code formatter
027 private Properties formatterSettings;
028
029
030 /**
031 * Constructor for CodeFormatter with default options
032 */
033 public CodeFormatter() {
034 this(null);
035 }
036
037 /**
038 * Constructor for CodeFormatter with given settings;
039 * if given null, loads default formatter settings
040 */
041 public CodeFormatter(Properties formatterSettings) {
042 setFormatterSettings(formatterSettings);
043 }
044
045 /**
046 * Formats source code using current formatter settings
047 */
048 public String format(String code) {
049
050 /*
051 * The settings map must at least contain these three options, or the JDT code formatter will not work.
052 * Check if these settings exist, otherwise emit a warning and return the unformatted source code.
053 */
054 if (!formatterSettings.containsKey(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM)) {
055 log.warn("Code formatter settings must define " + JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM);
056 return code;
057 }
058 if (!formatterSettings.containsKey(JavaCore.COMPILER_COMPLIANCE)) {
059 log.warn("Code formatter settings must define " + JavaCore.COMPILER_COMPLIANCE);
060 return code;
061 }
062 if (!formatterSettings.containsKey(JavaCore.COMPILER_SOURCE)) {
063 log.warn("Code formatter settings must define " + JavaCore.COMPILER_SOURCE);
064 return code;
065 }
066
067 // Load the code into an eclipse document
068 IDocument document = new Document();
069 document.set(code);
070
071 // Create the code formatter
072 org.eclipse.jdt.core.formatter.CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(this.formatterSettings);
073
074 /*
075 * Run the formatter and apply the modifications to the document.
076 * If it fails (probably due to a syntax error), just return the unformatted source code.
077 */
078 TextEdit modifications = codeFormatter.format(org.eclipse.jdt.core.formatter.CodeFormatter.K_COMPILATION_UNIT,
079 code, 0, code.length(), 0, null);
080 if (modifications != null) {
081 try {
082 modifications.apply(document);
083 } catch (Exception e) {
084 throw new RuntimeException(e);
085 }
086 }
087
088 // Return the document contents as string
089 return document.get();
090 }
091
092 /**
093 * Returns a Properties object representing containing all the code formatter options
094 */
095 public Properties getFormatterSettings() {
096 return formatterSettings;
097 }
098
099 /**
100 * Sets the formatter options;
101 * if given null, reverts to default formatter options
102 */
103 public void setFormatterSettings(Properties formatterSettings) {
104 if (formatterSettings != null) {
105 this.formatterSettings = formatterSettings;
106 } else {
107 this.formatterSettings = getDefaultSettings();
108 }
109 }
110
111 /**
112 * Loads default options from DEFAULT_OPTIONS_FILE
113 */
114 private static Properties getDefaultSettings() {
115 try {
116 InputStream inputStream = CodeFormattingWriter.class.getResourceAsStream(DEFAULT_SETTINGS_FILE);
117 if (inputStream != null) {
118 Properties options = new Properties();
119 options.load(inputStream);
120 return options;
121 } else {
122 throw new FileNotFoundException(DEFAULT_SETTINGS_FILE);
123 }
124 } catch (IOException e) {
125 throw new RuntimeException(e);
126 }
127 }
128 }