/*******************************************************************************
* Copyright (c) 2007-2009 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.hibernate.eclipse.console.actions;
import java.io.FileNotFoundException;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.SelectionListenerAction;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.hibernate.console.ConsoleConfiguration;
import org.hibernate.eclipse.console.HibernateConsoleMessages;
import org.hibernate.eclipse.console.HibernateConsolePlugin;
import org.hibernate.eclipse.console.utils.OpenMappingUtils;
import org.hibernate.eclipse.console.utils.ProjectUtils;
import org.jboss.tools.hibernate.runtime.spi.IPersistentClass;
import org.jboss.tools.hibernate.runtime.spi.IProperty;
import org.jboss.tools.hibernate.runtime.spi.IService;
/**
* Open Mapping File action
*
* @author Dmitry Geraskov
* @author Vitali Yemialyanchyk
*/
public class OpenMappingAction extends SelectionListenerAction {
public static final String OPENMAPPING_ACTIONID = "actionid.openmapping"; //$NON-NLS-1$
private final String imageFilePath = "icons/images/mapping.gif"; //$NON-NLS-1$
public OpenMappingAction() {
super(HibernateConsoleMessages.OpenMappingAction_open_mapping_file);
setToolTipText(HibernateConsoleMessages.OpenMappingAction_open_mapping_file);
setEnabled(true);
setImageDescriptor(HibernateConsolePlugin.getImageDescriptor(imageFilePath ));
setId(OPENMAPPING_ACTIONID);
}
public void run() {
IStructuredSelection sel = getStructuredSelection();
if (!(sel instanceof TreeSelection)) {
return;
}
TreePath[] paths = ((TreeSelection)sel).getPaths();
for (int i = 0; i < paths.length; i++) {
TreePath path = paths[i];
ConsoleConfiguration consoleConfig = (ConsoleConfiguration)(path.getSegment(0));
try {
run(consoleConfig, path);
} catch (JavaModelException e) {
HibernateConsolePlugin.getDefault().logErrorMessage(HibernateConsoleMessages.OpenMappingAction_cannot_find_mapping_file, e);
} catch (PartInitException e) {
HibernateConsolePlugin.getDefault().logErrorMessage(HibernateConsoleMessages.OpenMappingAction_cannot_open_mapping_file, e);
} catch (FileNotFoundException e) {
HibernateConsolePlugin.getDefault().logErrorMessage(HibernateConsoleMessages.OpenMappingAction_cannot_find_mapping_file, e);
}
}
}
/**
* @param path
* @param consoleConfig
* @return
* @throws PartInitException
* @throws JavaModelException
* @throws FileNotFoundException
*/
public static IEditorPart run(ConsoleConfiguration consoleConfig, TreePath path)
throws PartInitException, JavaModelException, FileNotFoundException {
boolean isPropertySel = (path.getLastSegment() instanceof IProperty && ((IProperty)path.getLastSegment()).classIsPropertyClass());
if (isPropertySel) {
IProperty propertySel = (IProperty)path.getLastSegment();
IPersistentClass persClass = propertySel.getPersistentClass();
if (persClass == null
|| (persClass.isAssignableToRootClass()
&& !persClass.isRootClass())) {
IProperty parentProp = (IProperty)path.getParentPath().getLastSegment();
return run(consoleConfig, propertySel, parentProp);
}
}
return run(consoleConfig, path.getLastSegment(), null);
}
/**
* @param consoleConfig
* @param selection
* @param selectionParent
* @throws JavaModelException
* @throws PartInitException
* @throws PresistanceClassNotFoundException
* @throws FileNotFoundException
*/
public static IEditorPart run(ConsoleConfiguration consoleConfig, Object selection, Object selectionParent) throws PartInitException, JavaModelException, FileNotFoundException {
IEditorPart editorPart = null;
IFile file = null;
if (selection instanceof IProperty) {
IProperty p = (IProperty)selection;
if (p.getPersistentClass() != null) {
//use PersistentClass to open editor
file = OpenMappingUtils.searchFileToOpen(consoleConfig, p.getPersistentClass());
}
}
else {
if (selectionParent != null) {
file = OpenMappingUtils.searchFileToOpen(consoleConfig, selectionParent);
} else {
file = OpenMappingUtils.searchFileToOpen(consoleConfig, selection);
}
}
if (file != null) {
editorPart = OpenMappingUtils.openFileInEditor(file);
IService service = consoleConfig.getHibernateExtension().getHibernateService();
boolean updateRes = updateEditorSelection(editorPart, selection, service);
if (!updateRes && selectionParent != null) {
// if it is not possible to select object, try to select it's parent
updateRes = updateEditorSelection(editorPart, selectionParent, service);
}
}
if (editorPart == null) {
//try to find hibernate-annotations
IPersistentClass rootClass = null;
if (selection instanceof IPersistentClass) {
rootClass = (IPersistentClass)selection;
}
else if (selection instanceof IProperty) {
IProperty p = (IProperty)selection;
if (p.getPersistentClass() != null) {
rootClass = p.getPersistentClass();
}
}
if (rootClass != null){
if (OpenMappingUtils.hasConfigXMLMappingClassAnnotation(consoleConfig, rootClass)) {
String fullyQualifiedName = rootClass.getClassName();
editorPart = OpenSourceAction.run(consoleConfig, selection, fullyQualifiedName);
}
}
}
if (editorPart == null) {
final String title = HibernateConsoleMessages.OpenMappingAction_open_mapping_file;
final String msg = NLS.bind(HibernateConsoleMessages.OpenMappingAction_mapping_for_not_found, selection);
MessageDialog.openError(null, title, msg);
throw new FileNotFoundException(msg);
}
return editorPart;
}
/**
* @param consoleConfig
* @param compositeProperty
* @param parentProperty
* @throws JavaModelException
* @throws PartInitException
* @throws FileNotFoundException
* @throws BadLocationException
*/
public static IEditorPart run(ConsoleConfiguration consoleConfig, IProperty compositeProperty, IProperty parentProperty)
throws PartInitException, JavaModelException, FileNotFoundException {
IPersistentClass rootClass = parentProperty.getPersistentClass();
IFile file = OpenMappingUtils.searchFileToOpen(consoleConfig, rootClass);
IEditorPart editorPart = null;
if (file != null){
editorPart = OpenMappingUtils.openFileInEditor(file);
IService service = consoleConfig.getHibernateExtension().getHibernateService();
updateEditorSelection(editorPart, compositeProperty, parentProperty, service);
}
if (editorPart == null && parentProperty.isComposite()) {
if (OpenMappingUtils.hasConfigXMLMappingClassAnnotation(consoleConfig, rootClass)) {
String fullyQualifiedName =parentProperty.getValue().getComponentClassName();
editorPart = OpenSourceAction.run(consoleConfig, compositeProperty, fullyQualifiedName);
}
}
if (editorPart == null) {
final String title = HibernateConsoleMessages.OpenMappingAction_open_mapping_file;
final String msg = NLS.bind(HibernateConsoleMessages.OpenMappingAction_mapping_file_for_property_not_found, compositeProperty.getName());
MessageDialog.openError(null, title, msg);
throw new FileNotFoundException(msg);
}
return editorPart;
}
/**
* @param editorPart
* @param selection
*/
public static boolean updateEditorSelection(IEditorPart editorPart, Object selection, IService service) {
ITextEditor[] textEditors = OpenMappingUtils.getTextEditors(editorPart);
if (textEditors.length == 0) {
return false;
}
textEditors[0].selectAndReveal(0, 0);
FindReplaceDocumentAdapter findAdapter = null;
ITextEditor textEditor = null;
for (int i = 0; i < textEditors.length && findAdapter == null; i++) {
textEditor = textEditors[i];
findAdapter = OpenMappingUtils.createFindDocAdapter(textEditor);
}
if (findAdapter == null) {
return false;
}
IJavaProject proj = ProjectUtils.findJavaProject(editorPart);
IRegion selectRegion = OpenMappingUtils.findSelectRegion(proj, findAdapter, selection, service);
if (selectRegion != null) {
if (editorPart instanceof MultiPageEditorPart) {
((MultiPageEditorPart)editorPart).setActiveEditor(textEditor);
}
textEditor.selectAndReveal(selectRegion.getOffset(), selectRegion.getLength());
return true;
}
return false;
}
/**
* @param editorPart
* @param compositeProperty
* @param parentProperty
*/
public static boolean updateEditorSelection(IEditorPart editorPart, IProperty compositeProperty, IProperty parentProperty, IService service) {
ITextEditor[] textEditors = OpenMappingUtils.getTextEditors(editorPart);
if (textEditors.length == 0) {
return false;
}
textEditors[0].selectAndReveal(0, 0);
FindReplaceDocumentAdapter findAdapter = null;
ITextEditor textEditor = null;
for (int i = 0; i < textEditors.length && findAdapter == null; i++) {
textEditor = textEditors[i];
findAdapter = OpenMappingUtils.createFindDocAdapter(textEditor);
}
if (findAdapter == null) {
return false;
}
IJavaProject proj = ProjectUtils.findJavaProject(editorPart);
IRegion parentRegion = OpenMappingUtils.findSelectRegion(proj, findAdapter, parentProperty, service);
if (parentRegion == null) {
return false;
}
int startOffset = parentRegion.getOffset() + parentRegion.getLength();
IRegion propRegion = null;
try {
final String hbmPropertyPattern = OpenMappingUtils.generateHbmPropertyPattern(compositeProperty, service);
propRegion = findAdapter.find(startOffset, hbmPropertyPattern, true, true, false, true);
IPersistentClass rootClass = parentProperty.getPersistentClass();
if (propRegion == null && parentProperty.isComposite()
&& (parentProperty.equals(rootClass.getIdentifierProperty()) ||
!rootClass.hasIdentifierProperty())) {
// try to use key-property
String pattern = hbmPropertyPattern.replaceFirst("<property", "<key-property"); //$NON-NLS-1$ //$NON-NLS-2$
propRegion = findAdapter.find(startOffset, pattern, true, true, false, true);
if (propRegion == null) {
// try to use key-many-to-one
pattern = hbmPropertyPattern.replaceFirst("<many-to-one", "<key-many-to-one"); //$NON-NLS-1$ //$NON-NLS-2$
propRegion = findAdapter.find(startOffset, pattern, true, true, false, true);
}
}
} catch (BadLocationException e) {
HibernateConsolePlugin.getDefault().logErrorMessage(HibernateConsoleMessages.OpenMappingAction_selection_not_found, e);
}
if (propRegion == null && parentProperty.isComposite()){
String[] componentPatterns = new String[]{
OpenMappingUtils.createPattern("embeddable", "class", parentProperty.getValue().getComponentClassName()), //$NON-NLS-1$ //$NON-NLS-2$
OpenMappingUtils.createPattern("embeddable", "class", OpenMappingUtils.getShortClassName( //$NON-NLS-1$//$NON-NLS-2$
parentProperty.getValue().getComponentClassName()))
};
IRegion componentRegion = null;
for (int i = 0; i < componentPatterns.length && componentRegion == null; i++) {
try {
componentRegion = findAdapter.find(0, componentPatterns[i], true, true, false, true);
} catch (BadLocationException e) {
//ignore
}
}
if (componentRegion != null){
try {
propRegion = findAdapter.find(parentRegion.getOffset() + parentRegion.getLength(),
OpenMappingUtils.generateOrmEmbeddablePropertyPattern(compositeProperty), true, true, false, true);
} catch (BadLocationException e) {
//ignore
}
}
}
if (propRegion == null) {
return false;
}
int length = compositeProperty.getName().length();
int offset = propRegion.getOffset() + propRegion.getLength() - length - 1;
propRegion = new Region(offset, length);
if (editorPart instanceof MultiPageEditorPart) {
((MultiPageEditorPart)editorPart).setActiveEditor(textEditor);
}
textEditor.selectAndReveal(propRegion.getOffset(), propRegion.getLength());
return true;
}
}