/*******************************************************************************
* Copyright (c) 2014 Red Hat Inc..
* 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:
* Rastislav Wagner (Red Hat)
* Mickael Istria (Red Hat Inc.)
*******************************************************************************/
package org.eclipse.swtbot.generator.jdt.editor.document;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swtbot.generator.framework.AnnotationRule;
import org.eclipse.swtbot.generator.framework.GenerationRule;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
public class ClassDocument extends Document {
private Set<String> imports;
private List<Method> methods;
private int lastOffset;
private List<AnnotationRule> classAnnotations;
private SourceViewer viewer;
public ClassDocument(String className, String parentClass) {
super();
if (parentClass != null) {
String[] segments = parentClass.split("\\.");
String simpleName = segments[segments.length - 1];
set("import " + parentClass + ";\n\n" +
"public class " + className + " extends " + simpleName + " {\n\n}");
} else {
set("public class " + className + " {\n\n}");
}
imports = new HashSet<String>();
imports.add("org.eclipse.swtbot.eclipse.finder.SWTBotEclipseTestCase");
methods = new ArrayList<Method>();
classAnnotations = new ArrayList<AnnotationRule>();
}
/**
* Adds rules action to document
* @param rule to get action from
*/
public void addGenerationRule(GenerationRule rule){
List<String> codes = rule.getActions();
if(getActiveMethod() == null){
return;
}
int offset = this.imports.size()+ 4 + this.classAnnotations.size();
offset = offset+ computeOffsetUntilActiveIsMet();
offset = offset + computeActiveMethodOffset();
List<String> text = new ArrayList<String>();
for(String code : codes){
text.add(" "+code + ";\n");
}
getActiveMethod().addCode(rule);
addText(offset, text);
if(rule.getImports() != null){
for(String im : rule.getImports()){
addImport(im);
}
}
}
private void addText(int offset, List<String> text){
MultiTextEdit edit = new MultiTextEdit();
try {
for(String t: text){
edit.addChild(new InsertEdit(getLineOffset(offset), t));
}
edit.apply(this);
} catch (MalformedTreeException e) {
e.printStackTrace();
} catch (BadLocationException e) {
e.printStackTrace();
}
updateColoring();
}
private void removeText(int offset){
MultiTextEdit edit = new MultiTextEdit();
try {
edit.addChild(new DeleteEdit(getLineOffset(offset),getLineLength(offset)));
edit.apply(this);
} catch (MalformedTreeException e) {
e.printStackTrace();
} catch (BadLocationException e) {
e.printStackTrace();
}
updateColoring();
}
/**
* Adds method to document
* @param methodName
*/
public void addMethod(String methodName){
int offset = this.imports.size()+3;
offset = offset + this.classAnnotations.size();
for(Method m: methods){
offset = offset+ m.getAllLinesSize()+3;
offset = offset+ m.getAnnotations().size();
}
Method method = new Method(methodName);
this.methods.add(method);
List<String> text = new ArrayList<String>();
text.add(" public void "+methodName+"(){" + "\n");
text.add(" }\n\n");
addText(offset, text);
setActiveMethod(methodName);
}
private void addImport(String importCode) {
if (this.imports.add(importCode)) {
List<String> text = new ArrayList<String>();
text.add("import "+importCode + ";\n");
addText(this.imports.size() - 1, text);
}
}
private void removeImport(String importCode){
if(this.imports.contains(importCode)){
String[] lines = this.get().split("\n");
for(int i=0;i<lines.length;i++){
if(lines[i].contains(importCode)){
this.imports.remove(importCode);
removeText(i);
return;
}
}
}
}
/**
* Sets active method
* @param methodName
*/
public void setActiveMethod(String methodName){
getActiveMethod().setActive(false);
for(Method m: methods){
if(m.getName().equals(methodName)){
m.setActive(true);
}
}
updateColoring();
}
/**
* Removes specified annotation
* @param rule
*/
public void removeAnnotation(AnnotationRule rule){
int offset=this.imports.size()+3 + this.classAnnotations.size();
offset = offset + computeOffsetUntilActiveIsMet();
offset = offset + getActiveMethod().getAnnotations().size()- getActiveMethod().getAnnotations().indexOf(rule)-1;
if(getActiveMethod().removeAnnotation(rule)){
removeText(offset);
if(!isAnnotationPresent(rule)){
removeImport(rule.getImportText());
}
}
}
/**
* Removes specified class annotation
* @param rule
*/
public void removeClassAnnotation(AnnotationRule rule){
if(classAnnotations.contains(rule)){
int offset=this.imports.size()+1 + classAnnotations.indexOf(rule);
removeText(offset);
classAnnotations.remove(rule);
if(!isAnnotationPresent(rule)){
removeImport(rule.getImportText());
}
}
}
/**
* Adds specified class annotation
* @param rule
*/
public void addClassAnnotation(AnnotationRule rule){
addImport(rule.getImportText());
int offset=this.imports.size()+1 + this.classAnnotations.size();
List<String> text = new ArrayList<String>();
text.add("@"+rule.getAnnotation()+"\n");
classAnnotations.add(rule);
addText(offset, text);
}
/**
* Adss specified annotation
* @param rule
*/
public void addAnnotation(AnnotationRule rule){
int offset=computeOffsetUntilActiveIsMet();
getActiveMethod().addAnnotation(rule);
addImport(rule.getImportText());
offset = offset+this.imports.size()+3 + this.classAnnotations.size();
List<String> text = new ArrayList<String>();
text.add(" @"+rule.getAnnotation()+"\n");
addText(offset, text);
}
public Method getActiveMethod(){
for(Method m: methods){
if(m.isActive()){
return m;
}
}
return null;
}
public int getLastOffset() {
return lastOffset;
}
private void setLastOffset(int lastOffset) {
this.lastOffset = lastOffset;
}
/**
* Returns all currently used class annotations
*/
public List<AnnotationRule> getClassAnnotations() {
return classAnnotations;
}
private boolean isAnnotationPresent(AnnotationRule rule){
if(this.classAnnotations.contains(rule)){
return true;
}
for(Method m: methods){
for(AnnotationRule r: m.getAnnotations()){
if(r.equals(rule)){
return true;
}
}
}
return false;
}
private int getMethodLinesB() {
int i =0;
int methodLinesB = this.imports.size()+3 + this.classAnnotations.size();
Method activeMethod = methods.get(i);
while(!activeMethod.isActive()){
i++;
methodLinesB = methodLinesB+ activeMethod.getAllLinesSize()+3;
methodLinesB = methodLinesB+ activeMethod.getAnnotations().size();
activeMethod = methods.get(i);
}
return methodLinesB;
}
private void updateColoring(){
if(viewer != null){
if(getActiveMethod() != null){
viewer.getTextWidget().setLineBackground(0,viewer.getTextWidget().getLineCount() , viewer.getTextWidget().getLineBackground(0));
Color orange = new Color(Display.getCurrent(), 205, 205, 201);
int methodsCodeSize = getActiveMethod().getAllLinesSize();
viewer.getTextWidget().setLineBackground(getMethodLinesB(), getActiveMethod().getAnnotations().size() + methodsCodeSize +2, orange);
setLastOffset(getMethodLinesB()+getActiveMethod().getAnnotations().size() + methodsCodeSize);
}
}
}
private int computeOffsetUntilActiveIsMet(){
int i =0;
int offset=0;
Method activeMethod = methods.get(i);
while(!activeMethod.isActive()){
i++;
offset = offset+ activeMethod.getAllLinesSize()+3;
offset = offset+ activeMethod.getAnnotations().size();
activeMethod = methods.get(i);
}
return offset;
}
private int computeActiveMethodOffset(){
return getActiveMethod().getAllLinesSize() + getActiveMethod().getAnnotations().size();
}
public void setViewer(SourceViewer generatedCode) {
viewer = generatedCode;
}
/**
* Returns all methods in document
* @return
*/
public List<Method> getMethods(){
return methods;
}
}