content: /*******************************************************************************
   * Copyright (c) 2000, 2008 IBM Corporation and others.
   * 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:
   *     IBM Corporation - initial API and implementation
   *******************************************************************************/
  package org.eclipse.wst.jsdt.internal.ui.fix;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.jface.text.BadLocationException;
  import org.eclipse.jface.text.Document;
  import org.eclipse.jface.text.IDocument;
  import org.eclipse.jface.text.ITypedRegion;
  import org.eclipse.jface.text.TextUtilities;
  import org.eclipse.jface.text.TypedPosition;
  import org.eclipse.jface.text.formatter.FormattingContextProperties;
  import org.eclipse.jface.text.formatter.IFormattingContext;
  import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
  import org.eclipse.ltk.core.refactoring.GroupCategory;
  import org.eclipse.ltk.core.refactoring.GroupCategorySet;
  import org.eclipse.ltk.core.refactoring.TextChange;
  import org.eclipse.text.edits.MalformedTreeException;
  import org.eclipse.text.edits.MultiTextEdit;
  import org.eclipse.text.edits.ReplaceEdit;
  import org.eclipse.text.edits.TextEdit;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.JavaScriptCore;
  import org.eclipse.wst.jsdt.internal.corext.fix.IFix;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.changes.CompilationUnitChange;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.StatusInfo;
  import org.eclipse.wst.jsdt.internal.ui.text.comment.CommentFormattingContext;
  import org.eclipse.wst.jsdt.internal.ui.text.comment.CommentFormattingStrategy;
  import org.eclipse.wst.jsdt.ui.text.IJavaScriptPartitions;
  
  public class CommentFormatFix implements IFix {
  	
  	public static IFix createCleanUp(IJavaScriptUnit unit, boolean singleLine, boolean multiLine, boolean javaDoc, HashMap preferences) throws CoreException {
  		if (!singleLine && !multiLine && !javaDoc)
  			return null;
  		
  		String content= unit.getBuffer().getContents();
  		Document document= new Document(content);
  		
  		final List edits= format(document, singleLine, multiLine, javaDoc, preferences);
  		
  		if (edits.size() == 0)
  			return null;
  		
  		MultiTextEdit resultEdit= new MultiTextEdit();
  		resultEdit.addChildren((TextEdit[])edits.toArray(new TextEdit[edits.size()]));
  		
  		TextChange change= new CompilationUnitChange(MultiFixMessages.CommentFormatFix_description, unit);
  		change.setEdit(resultEdit);
  		
  		String label= MultiFixMessages.CommentFormatFix_description;
  		CategorizedTextEditGroup group= new CategorizedTextEditGroup(label, new GroupCategorySet(new GroupCategory(label, label, label)));
  		group.addTextEdit(resultEdit);
  		change.addTextEditGroup(group);
  		
  		return new CommentFormatFix(change, unit);
  	}
  	
  	static String format(String input, boolean singleLine, boolean multiLine, boolean javaDoc) {
  		if (!singleLine && !multiLine && !javaDoc)
  			return input;
  		
  		HashMap preferences= new HashMap(JavaScriptCore.getOptions());
  		Document document= new Document(input);
  		List edits= format(document, singleLine, multiLine, javaDoc, preferences);
  		
  		if (edits.size() == 0)
  			return input;
  		
  		MultiTextEdit resultEdit= new MultiTextEdit();
  		resultEdit.addChildren((TextEdit[])edits.toArray(new TextEdit[edits.size()]));
  		
  		try {
  			resultEdit.apply(document);
  		} catch (MalformedTreeException e) {
  			JavaScriptPlugin.log(e);
  		} catch (BadLocationException e) {
  			JavaScriptPlugin.log(e);
  		}
  		return document.get();
  	}
  	
  	private static List format(IDocument document, boolean singleLine, boolean multiLine, boolean javaDoc, HashMap preferences) {
  		final List edits= new ArrayList();
  		
  		JavaScriptPlugin.getDefault().getJavaTextTools().setupJavaDocumentPartitioner(document, IJavaScriptPartitions.JAVA_PARTITIONING);
  		
  		String content= document.get();
  		
  		CommentFormattingStrategy formattingStrategy= new CommentFormattingStrategy();
  		
  		IFormattingContext context= new CommentFormattingContext();
  		context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, preferences);
  		context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.TRUE);
  		context.setProperty(FormattingContextProperties.CONTEXT_MEDIUM, document);
  		
  		try {
  			ITypedRegion[] regions= TextUtilities.computePartitioning(document, IJavaScriptPartitions.JAVA_PARTITIONING, 0, document.getLength(), false);
  			for (int i= 0; i < regions.length; i++) {
  				ITypedRegion region= regions[i];
  				if (singleLine && region.getType().equals(IJavaScriptPartitions.JAVA_SINGLE_LINE_COMMENT)) {
  					TextEdit edit= format(region, context, formattingStrategy, content);
  					if (edit != null)
  						edits.add(edit);
  				} else if (multiLine && region.getType().equals(IJavaScriptPartitions.JAVA_MULTI_LINE_COMMENT)) {
  					TextEdit edit= format(region, context, formattingStrategy, content);
  					if (edit != null)
  						edits.add(edit);
  				} else if (javaDoc && region.getType().equals(IJavaScriptPartitions.JAVA_DOC)) {
  					TextEdit edit= format(region, context, formattingStrategy, content);
  					if (edit != null)
  						edits.add(edit);
  				}
  			}
  		} catch (BadLocationException e) {
  			JavaScriptPlugin.log(e);
  		} finally {
  			context.dispose();
  		}
  		
  		return edits;
  	}
  	
  	private static TextEdit format(ITypedRegion region, IFormattingContext context, CommentFormattingStrategy formattingStrategy, String content) {
  		TypedPosition typedPosition= new TypedPosition(region.getOffset(), region.getLength(), region.getType());
  		context.setProperty(FormattingContextProperties.CONTEXT_PARTITION, typedPosition);
  		formattingStrategy.formatterStarts(context);
  		TextEdit edit= formattingStrategy.calculateTextEdit();
  		formattingStrategy.formatterStops();
  		if (edit == null)
  			return null;
  		
  		if (!edit.hasChildren())
  			return null;
  		
  		// Filter out noops
  		TextEdit[] children= edit.getChildren();
  		for (int i= 0; i < children.length; i++) {
  			if (!(children[i] instanceof ReplaceEdit))
  				return edit;
  		}
  		
  		IDocument doc= new Document(content);
  		try {
  			edit.copy().apply(doc, TextEdit.NONE);
  			if (content.equals(doc.get()))
  				return null;
  		} catch (MalformedTreeException e) {
  		} catch (BadLocationException e) {
  		}
  		
  		return edit;
  	}
  	
  	private final IJavaScriptUnit fCompilationUnit;
  	private final TextChange fChange;
  	
  	public CommentFormatFix(TextChange change, IJavaScriptUnit compilationUnit) {
  		fChange= change;
  		fCompilationUnit= compilationUnit;
  	}
  	
  	/**
  	 * {@inheritDoc}
  	 */
  	public TextChange createChange() throws CoreException {
  		return fChange;
  	}
  	
  	/**
  	 * {@inheritDoc}
  	 */
  	public IJavaScriptUnit getCompilationUnit() {
  		return fCompilationUnit;
  	}
  	
  	/**
  	 * {@inheritDoc}
  	 */
  	public String getDescription() {
  		return MultiFixMessages.CommentFormatFix_description;
  	}
  	
  	/**
  	 * {@inheritDoc}
  	 */
  	public IStatus getStatus() {
  		return StatusInfo.OK_STATUS;
  	}
  }
  