/*
* Copyright 2014 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onehippo.intellij.groovy;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.onehippo.intellij.groovy.config.ApplicationComponent;
import org.onehippo.intellij.groovy.config.ProjectComponent;
import com.google.common.base.Strings;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
/**
* @version "$Id$"
*/
public class GroovyEditor extends AnAction {
public static final NotificationGroup ERROR_GROUP = new NotificationGroup("Hippo Groovy editor error messages", NotificationDisplayType.BALLOON, true);
public static final NotificationGroup INFO_GROUP = new NotificationGroup("Hippo Groovy editor info messages", NotificationDisplayType.NONE, false);
private Project project;
protected static void error(final String message, final Project project) {
final Notification notification = ERROR_GROUP.createNotification(message, NotificationType.ERROR);
notification.notify(project);
}
private void info(final String message) {
final Notification notification = INFO_GROUP.createNotification(message, NotificationType.INFORMATION);
notification.notify(project);
}
private void warn(final String message) {
final Notification notification = INFO_GROUP.createNotification(message, NotificationType.WARNING);
notification.notify(project);
}
@Override
public void actionPerformed(final AnActionEvent event) {
project = CommonDataKeys.PROJECT.getData(event.getDataContext());
if (project != null) {
Editor editor = CommonDataKeys.EDITOR.getData(event.getDataContext());
if (editor == null || editor.getDocument() == null) {
return;
}
final VirtualFile canonicalFile = project.getBaseDir().getCanonicalFile();
if (canonicalFile == null) {
return;
}
final VirtualFile currentFile = CommonDataKeys.VIRTUAL_FILE.getData(event.getDataContext());
final CharSequence charsSequence = editor.getDocument().getCharsSequence();
final RepositoryConnector connector = new RepositoryConnector(project);
final ApplicationComponent component = project.getComponent(ProjectComponent.class);
String groovyFolder = canonicalFile.getPath() + File.separator + RepositoryConnector.GROOVY_FOLDER;
if (component != null) {
final String groovyDirectory = component.getGroovyDirectory();
if (!Strings.isNullOrEmpty(groovyDirectory)) {
groovyFolder = groovyDirectory;
}
}
saveFile(connector, groovyFolder, currentFile, charsSequence.toString());
}
}
public void saveFile(final RepositoryConnector connector, final String groovyFolder, final VirtualFile currentFile, final String content) {
String path = currentFile.getPath();
// check if file is within groovy root folder
if (!path.startsWith(groovyFolder)) {
error("File: " + path + " is not within Groovy root folder", project);
return;
}
path = path.substring(groovyFolder.length(), path.length());
Session session = null;
try {
session = connector.getSession();
final int fileNameIndex = path.lastIndexOf('/');
String separator = path.startsWith("/") ? "" : "/";
final String fileName = path.substring(fileNameIndex, path.length());
final String templateRoot = "/hst:hst/hst:configurations" + separator + path.substring(0, fileNameIndex) + "/hst:templates";
String absPath = templateRoot + fileName;
absPath = absPath.replaceAll("hst_default", "hst:default");
if (session.nodeExists(absPath)) {
final Node node = session.getNode(absPath);
node.setProperty("hst:script", content);
session.save();
} else {
showCreatePopup(fileName, templateRoot, content, session);
}
} catch (RepositoryException e) {
} finally {
if (session != null) {
session.logout();
}
}
}
private void showCreatePopup(final String fileName, final String templateRoot, final String content, final Session session) {
final DialogBuilder dialogBuilder = new DialogBuilder(project);
dialogBuilder.setTitle("Create new template node:");
final JPanel simplePanel = new JPanel();
simplePanel.add(new JLabel("Node doesn't exist, should we create one? (" + templateRoot + fileName + ')'));
dialogBuilder.setCenterPanel(simplePanel);
final Action acceptAction = new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(final ActionEvent e) {
try {
final String root = templateRoot.endsWith("/") ? templateRoot.substring(0, templateRoot.length() - 1) : templateRoot;
// check if site node exists:
if (!session.nodeExists(root)) {
final String configRoot = "/hst:hst/hst:configurations/";
final String newSiteName = (root.substring(configRoot.length())).replaceAll("/hst:templates/|/hst:templates", "");
final Node configRootNode = session.getNode(configRoot);
final Node siteNode = configRootNode.addNode(newSiteName, "hst:configuration");
siteNode.addMixin("mix:referenceable");
siteNode.addMixin("mix:simpleVersionable");
siteNode.addMixin("mix:versionable");
final Node templateNode = siteNode.addNode("hst:templates", "hst:templates");
templateNode.addMixin("mix:referenceable");
}
final Node node = session.getNode(root);
final String nodeName = fileName.startsWith(File.separator) ? fileName.substring(1, fileName.length()) : fileName;
final Node templateNode = node.addNode(nodeName, "hst:template");
templateNode.setProperty("hst:script", content);
session.save();
} catch (RepositoryException e1) {
GroovyEditor.error("Error writing template, " + e1.getMessage(), project);
try {
session.refresh(false);
} catch (RepositoryException e2) {
//
}
}
dialogBuilder.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE);
}
};
acceptAction.putValue(Action.NAME, "OK");
dialogBuilder.addAction(acceptAction);
dialogBuilder.addCancelAction();
dialogBuilder.showModal(true);
}
}