package tk.eclipse.plugin.htmleditor;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import jp.aonir.fuzzyxml.FuzzyXMLElement;
import jp.aonir.fuzzyxml.FuzzyXMLNode;
import jp.aonir.fuzzyxml.XPath;
import jp.aonir.fuzzyxml.internal.FuzzyXMLUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;
/**
* This provides utility methods.
*
* @author Naoki Takezoe
*/
public class HTMLUtil {
/**
* Returns whether the <code>IResourceDelta</code> contains
* the specified <code>IFile</code>.
*
* @param delta the <code>IResourceDelta</code>
* @param file the <code>IFile</code>
* @return true if the file is contained, otherwise false
*/
public static boolean contains(IResourceDelta delta, IFile file){
IResourceDelta member = delta.findMember(file.getFullPath());
if(member==null){
return false;
}
return true;
}
/**
* Copy folder.
*
* @param from the target folder
* @param to the destination folder
* @throws IOException when I/O error occurs
*/
public static void copyFolder(File from, File to) throws IOException {
File[] files = from.listFiles();
for(int i=0;i<files.length;i++){
if(files[i].isDirectory()){
File newDir = new File(to,files[i].getName());
if(!newDir.exists()){
newDir.mkdir();
copyFolder(files[i],newDir);
}
} else {
File newFile = new File(to,files[i].getName());
if(!newFile.exists()){
InputStream in = new FileInputStream(files[i]);
OutputStream out = new FileOutputStream(newFile);
byte[] buf = new byte[1027 * 8];
int length = 0;
while((length=in.read(buf))!=-1){
out.write(buf,0,length);
}
in.close();
out.close();
}
}
}
}
/**
* Escape HTML special characters.
*
* @param str the raw string
* @return the escaped string
*/
public static String escapeHTML(String str){
return FuzzyXMLUtil.escape(str, true);
}
/**
* Replaces comments of CSS with whitespaces.
*
* @param source CSS source code
* @return processed source code
*/
public static String cssComment2space(String source){
int index = 0;
int last = 0;
StringBuffer sb = new StringBuffer();
while((index = source.indexOf("/*",last))!=-1){
int end = source.indexOf("*/",index);
if(end!=-1){
sb.append(source.substring(last,index));
int length = end - index + 2;
for(int i=0;i<length;i++){
sb.append(" ");
}
} else {
break;
}
last = end + 2;
}
if(last != source.length()-1){
sb.append(source.substring(last));
}
return sb.toString();
}
/**
* Replace comments of HTML/JSP/XML with whitespaces.
*
* <ul>
* <li>replace <!-- ... --> to the whitespaces</li>
* <li>replace <%-- ... --%> to the whitespaces</li>
* </ul>
*
* @param source source code of the HTML/JSP/XML
* @param contentsOnly
* <ul>
* <li>true - <!--�A--> and <%--�A--%> are not replaced.<li>
* <li>false - <!--�A--> and <%--�A--%> are also replaced.<li>
* </ul>
* @return processed source code
*/
public static String comment2space(String source,boolean contentsOnly){
source = jspComment2space(source,contentsOnly);
source = FuzzyXMLUtil.comment2space(source,contentsOnly);
return source;
}
/**
* Replace comments of the JSP with whitespaces.
*
* @param source source code of the JSP
* @param contentsOnly
* <ul>
* <li>true - <%�A%> are not replaced.</li>
* <li>false - <%�A%> are also replaced.</li>
* </ul>
* @return processed source code
*/
public static String jspComment2space(String source,boolean contentsOnly){
int index = 0;
int last = 0;
StringBuffer sb = new StringBuffer();
while((index = source.indexOf("<%--",last))!=-1){
int end = source.indexOf("--%>",index);
if(end!=-1){
sb.append(source.substring(last,index));
int length = end - index + 4;
if(contentsOnly){
sb.append("<%--");
length = length - 8;
}
for(int i=0;i<length;i++){
sb.append(" ");
}
if(contentsOnly){
sb.append("--%>");
}
} else {
break;
}
last = end + 4;
}
if(last != source.length()-1){
sb.append(source.substring(last));
}
return sb.toString();
}
/**
* Replace scriptlet in the JSP to whitespaces.
*
* @param source source code of the JSP
* @param contentsOnly
* <ul>
* <li>true - <%�A%> are not replaced.
* <li>false - <%�A%> are also replaced.
* </ul>
* @return processed source code
*/
public static String scriptlet2space(String source,boolean contentsOnly){
int index = 0;
int last = 0;
StringBuffer sb = new StringBuffer();
while((index = source.indexOf("<%",last))!=-1){
int end = source.indexOf("%>",index);
if(end!=-1){
sb.append(source.substring(last,index));
int length = end - index + 2;
if(contentsOnly){
sb.append("<%");
length = length - 4;
}
for(int i=0;i<length;i++){
sb.append(" ");
}
if(contentsOnly){
sb.append("%>");
}
} else {
break;
}
last = end + 2;
}
if(last != source.length()-1){
sb.append(source.substring(last));
}
return sb.toString();
}
// /** Copy a list */
// public static List cloneList(List from){
// List result = new ArrayList();
// for(int i=0;i<from.size();i++){
// result.add(from.get(i));
// }
// return result;
// }
/**
* Returns stream contents as a byte array.
*/
public static byte[] readStream(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024 * 8];
while((len = in.read(buf))!=-1){
out.write(buf,0,len);
}
byte[] result = out.toByteArray();
in.close();
out.close();
return result;
}
/**
* Escape XML string.
* <p>
* If value is null, this method returns an empty string.
* </p>
* @param value string
* @return escaped string
*/
public static String escapeXML(String value){
return FuzzyXMLUtil.escape(value, false);
}
/**
* Wrapps XPath#getValue() of FuzzyXML.
* This method provides following additional features.
*
* <ul>
* <li>returns null when exceptions are caused.</li>
* <li>trims a return value.</li>
* </ul>
*
* @param element the base element
* @param xpath XPath
* @return the selected value or null
*/
public static String getXPathValue(FuzzyXMLElement element,String xpath){
try {
String value = (String)XPath.getValue(element,xpath);
return value.trim();
} catch(Exception ex){
return null;
}
}
public static FuzzyXMLNode selectXPathNode(FuzzyXMLElement element,String xpath){
try {
return XPath.selectSingleNode(element,xpath);
} catch(Exception ex){
return null;
}
}
public static FuzzyXMLNode[] selectXPathNodes(FuzzyXMLElement element,String xpath){
try {
return XPath.selectNodes(element,xpath);
} catch(Exception ex){
return new FuzzyXMLNode[0];
}
}
/**
* Returns an empty string if an argument is null.
*/
public static String nullConv(String value){
if(value==null){
return "";
}
return value;
}
/**
* Creates a Document object from InputStream.
*
* @param in InputStream of a XML document
* @param resolver EntityResolver or null
* @return Document object
* @throws ParserConfigurationException
* @throws FactoryConfigurationError
* @throws SAXException
* @throws IOException
*/
public static Document createDocument(InputStream in,EntityResolver resolver)
throws ParserConfigurationException, FactoryConfigurationError, SAXException, IOException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
if(resolver!=null){
builder.setEntityResolver(resolver);
}
Document doc = builder.parse(in);
return doc;
}
/**
* Sorts informations of code completion in alphabetical order.
*
* @param prop the list of ICompletionProposal
*/
public static void sortCompilationProposal(List prop){
Collections.sort(prop,new Comparator(){
public int compare(Object o1,Object o2){
ICompletionProposal c1 = (ICompletionProposal)o1;
ICompletionProposal c2 = (ICompletionProposal)o2;
return c1.getDisplayString().compareTo(c2.getDisplayString());
}
});
}
/**
* Returns a project encoding.
*
* @param project project
* @return encoding
*/
public static String getProjectCharset(IProject project){
try {
String charset = project.getDefaultCharset();
if(charset.equals("MS932")){
// charset = "Shift_JIS";
charset = "Windows-31J";
}
return charset;
} catch(Exception ex){
HTMLPlugin.logException(ex);
}
return null;
}
/**
* Adds marker to the specified line.
*
* @param resource the target resource
* @param type the error type that defined by IMaker
* @param line the line number
* @param message the error message
*/
public static void addMarker(IResource resource, int type, int line, String message){
try {
IMarker marker = resource.createMarker(IMarker.PROBLEM);
Map map = new HashMap();
map.put(IMarker.SEVERITY, new Integer(type));
map.put(IMarker.MESSAGE, message);
map.put(IMarker.LINE_NUMBER,new Integer(line));
marker.setAttributes(map);
} catch(CoreException ex){
HTMLPlugin.logException(ex);
}
}
/**
* Adds task marker to the specified range.
*
* @param resource the target resource
* @param priority the priority that defined by IMaker
* @param line the line number
* @param offset the offset
* @param length the length
* @param message the error message
*/
public static void addTaskMarker(IResource resource,int priority, int line, String message){
try {
IMarker marker = resource.createMarker(IMarker.TASK);
Map map = new HashMap();
map.put(IMarker.PRIORITY, new Integer(priority));
map.put(IMarker.MESSAGE, message);
map.put(IMarker.LINE_NUMBER,new Integer(line));
marker.setAttributes(map);
} catch(CoreException ex){
HTMLPlugin.logException(ex);
}
}
/**
* Adds marker to the specified range.
*
* @param resource the target resource
* @param type the error type that defined by IMaker
* @param line the line number
* @param offset the offset
* @param length the length
* @param message the error message
*/
public static void addMarker(IResource resource,int type, int line, int offset,int length,String message){
try {
IMarker marker = resource.createMarker(IMarker.PROBLEM);
Map map = new HashMap();
map.put(IMarker.SEVERITY, new Integer(type));
map.put(IMarker.MESSAGE, message);
map.put(IMarker.CHAR_START,new Integer(offset));
map.put(IMarker.CHAR_END,new Integer(offset + length));
map.put(IMarker.LINE_NUMBER,new Integer(line));
marker.setAttributes(map);
} catch(CoreException ex){
HTMLPlugin.logException(ex);
}
}
/**
* Trim all elements in the array.
*
* @param array The string array
*/
public static void trim(String[] array){
for(int i=0;i<array.length;i++){
array[i] = array[i].trim();
}
}
/**
* Returns the first child element of the specified element.
*
* @param element the element
* @return the first child element
*/
public static FuzzyXMLElement getFirstElement(FuzzyXMLElement element){
FuzzyXMLNode[] nodes = element.getChildren();
for(int i=0;i<nodes.length;i++){
if(nodes[i] instanceof FuzzyXMLElement){
return (FuzzyXMLElement)nodes[i];
}
}
return null;
}
/**
* Converts {@link RGB} to the hex string.
*
* @param color the RGB object
* @return the hex string
*/
public static String toHex(RGB color){
StringBuffer sb = new StringBuffer();
sb.append("#").
append(toHex(color.red)).
append(toHex(color.green)).
append(toHex(color.blue));
return sb.toString();
}
private static String toHex(int value){
String hex = Integer.toHexString(value);
if(hex.length()==1){
hex = "0" + hex;
}
return hex;
}
/**
* Converts the hex string to {@link RGB}.
*
* @param value the hex string
* @return {@link RGB}
*/
public static RGB toRGB(String value){
if(value.startsWith("#")){
String red = value.substring(1, 3);
String green = value.substring(3, 5);
String blue = value.substring(5, 7);
return new RGB(toDecimal(red), toDecimal(green), toDecimal(blue));
}
return null;
}
private static int toDecimal(String value){
int result = 0;
int count = 1;
for(int i=value.length()-1;i>=0;i--){
char c = value.charAt(i);
if(c>='0' && c<='9'){
result += Integer.parseInt(String.valueOf(c)) * count;
} else if(c>='a' || c<='f'){
result += (c - 'a' + 10) * count;
} else if(c>='A' || c<='F'){
result += (c - 'A' + 10) * count;
}
count = count * 16;
}
return result;
}
/**
* Returns the getter method name from the property name.
*
* @param propertyName the property name
* @param isBool
* <ul>
* <li>true - returns isXxxx</li>
* <li>false - returns getXxxx</li>
* </ul>
* @return the getter method name
*/
public static String getGetterName(String propertyName, boolean isBool){
if(isBool){
return "is" + propertyName.substring(0, 1).toUpperCase() +
propertyName.substring(1);
} else {
return "get" + propertyName.substring(0, 1).toUpperCase() +
propertyName.substring(1);
}
}
/**
* Returns the setter method name from the property name.
*
* @param propertyName the propery name
* @return the setter method name
*/
public static String getSetterName(String propertyName){
return "set" + propertyName.substring(0, 1).toUpperCase() +
propertyName.substring(1);
}
/**
* Returns an active editor part in the workbench.
*
* @return An instance of an active editorpart.
*/
public static IEditorPart getActiveEditor(){
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
IWorkbenchPage page = window.getActivePage();
IEditorPart editorPart = page.getActiveEditor();
return editorPart;
}
}