diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-01-08 11:11:20 -0800 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-01-08 11:11:20 -0800 |
commit | b56ea2a18f232d79481e778085fd64e8ae486fc3 (patch) | |
tree | 44e1f6eb4864a45033f865b74fe783e3d784dd6a /plugins/devkit/src/actions/ShowSerializedXmlAction.java | |
download | idea-b56ea2a18f232d79481e778085fd64e8ae486fc3.tar.gz |
Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
Diffstat (limited to 'plugins/devkit/src/actions/ShowSerializedXmlAction.java')
-rw-r--r-- | plugins/devkit/src/actions/ShowSerializedXmlAction.java | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/plugins/devkit/src/actions/ShowSerializedXmlAction.java b/plugins/devkit/src/actions/ShowSerializedXmlAction.java new file mode 100644 index 000000000000..9ef05e35f014 --- /dev/null +++ b/plugins/devkit/src/actions/ShowSerializedXmlAction.java @@ -0,0 +1,241 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * 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.jetbrains.idea.devkit.actions; + +import com.intellij.CommonBundle; +import com.intellij.compiler.impl.FileSetCompileScope; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.compiler.CompileContext; +import com.intellij.openapi.compiler.CompileStatusNotification; +import com.intellij.openapi.compiler.CompilerManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderEnumerator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.ClassUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.FList; +import com.intellij.util.lang.UrlClassLoader; +import com.intellij.util.xmlb.Accessor; +import com.intellij.util.xmlb.XmlSerializer; +import com.intellij.util.xmlb.XmlSerializerUtil; +import org.jdom.Element; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.lang.reflect.Array; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; + +/** + * @author nik + */ +public class ShowSerializedXmlAction extends DumbAwareAction { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.devkit.actions.ShowSerializedXmlAction"); + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(getEventProject(e) != null && e.getData(LangDataKeys.PSI_FILE) != null + && e.getData(PlatformDataKeys.EDITOR) != null); + } + + @Override + public void actionPerformed(AnActionEvent e) { + final PsiClass psiClass = getPsiClass(e); + if (psiClass == null) return; + + final VirtualFile virtualFile = psiClass.getContainingFile().getVirtualFile(); + final Module module = ModuleUtilCore.findModuleForPsiElement(psiClass); + if (module == null || virtualFile == null) return; + + final String className = ClassUtil.getJVMClassName(psiClass); + + final Project project = getEventProject(e); + CompilerManager.getInstance(project).make(new FileSetCompileScope(Arrays.asList(virtualFile), new Module[]{module}), new CompileStatusNotification() { + @Override + public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) { + if (aborted || errors > 0) return; + generateAndShowXml(module, className); + } + }); + } + + private static void generateAndShowXml(final Module module, final String className) { + final List<URL> urls = new ArrayList<URL>(); + final List<String> list = OrderEnumerator.orderEntries(module).recursively().runtimeOnly().getPathsList().getPathList(); + for (String path : list) { + try { + urls.add(new File(FileUtil.toSystemIndependentName(path)).toURI().toURL()); + } + catch (MalformedURLException e1) { + LOG.info(e1); + } + } + + final Project project = module.getProject(); + UrlClassLoader loader = new UrlClassLoader(urls, XmlSerializer.class.getClassLoader()); + final Class<?> aClass; + try { + aClass = Class.forName(className, true, loader); + } + catch (ClassNotFoundException e) { + Messages.showErrorDialog(project, "Cannot find class '" + className + "'", CommonBundle.getErrorTitle()); + LOG.info(e); + return; + } + + final Object o; + try { + o = new SampleObjectGenerator().createValue(aClass, FList.<Type>emptyList()); + } + catch (Exception e) { + Messages.showErrorDialog(project, "Cannot generate class '" + className + "': " + e.getMessage(), CommonBundle.getErrorTitle()); + LOG.info(e); + return; + } + + final Element element = XmlSerializer.serialize(o); + final String text = JDOMUtil.writeElement(element, "\n"); + Messages.showInfoMessage(project, text, "Serialized XML for '" + className + "'"); + } + + @Nullable + private static PsiClass getPsiClass(AnActionEvent e) { + final PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + if (editor == null || psiFile == null) return null; + final PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset()); + return PsiTreeUtil.getParentOfType(element, PsiClass.class); + } + + private static class SampleObjectGenerator { + private int myNum; + + @Nullable + public Object createValue(Type type, final FList<Type> types) throws Exception { + if (types.contains(type)) return null; + FList<Type> processedTypes = types.prepend(type); + final Class<?> valueClass = type instanceof Class ? (Class<Object>)type : (Class<Object>)((ParameterizedType)type).getRawType(); + if (String.class.isAssignableFrom(valueClass)) { + return "value" + (myNum++); + } + else if (byte.class.isAssignableFrom(valueClass) || Byte.class.isAssignableFrom(valueClass) + || short.class.isAssignableFrom(valueClass) || Short.class.isAssignableFrom(valueClass) + || int.class.isAssignableFrom(valueClass) || Integer.class.isAssignableFrom(valueClass) + || long.class.isAssignableFrom(valueClass) || Long.class.isAssignableFrom(valueClass)) { + return myNum++ % 127; + } + else if (double.class.isAssignableFrom(valueClass) || Double.class.isAssignableFrom(valueClass) + || float.class.isAssignableFrom(valueClass) || Float.class.isAssignableFrom(valueClass)) { + return 0.5 + myNum++; + } + else if (boolean.class.isAssignableFrom(valueClass) || Boolean.class.isAssignableFrom(valueClass)) { + return (myNum++ % 2) == 0; + } + else if (valueClass.isEnum()) { + final Object[] constants = valueClass.getEnumConstants(); + return constants[(myNum++) % constants.length]; + } + else if (Collection.class.isAssignableFrom(valueClass) && type instanceof ParameterizedType) { + return createCollection(valueClass, (ParameterizedType)type, processedTypes); + } + else if (Map.class.isAssignableFrom(valueClass) && type instanceof ParameterizedType) { + return createMap((ParameterizedType)type, processedTypes); + } + else if (valueClass.isArray()) { + return createArray(valueClass, processedTypes); + } + else if (Element.class.isAssignableFrom(valueClass)) { + return new Element("customElement" + (myNum++)).setAttribute("attribute", "value" + (myNum++)).addContent(new Element("child" + (myNum++))); + } + else { + return createObject(valueClass, processedTypes); + } + } + + public Object createObject(Class<?> aClass, FList<Type> processedTypes) throws Exception { + final Object o = aClass.newInstance(); + for (Accessor accessor : XmlSerializerUtil.getAccessors(aClass)) { + final Type type = accessor.getGenericType(); + Object value = createValue(type, processedTypes); + if (value != null) { + accessor.write(o, value); + } + } + return o; + } + + @Nullable + private Object createArray(Class<?> valueClass, FList<Type> processedTypes) throws Exception { + final Object[] array = (Object[])Array.newInstance(valueClass.getComponentType(), 2); + for (int i = 0; i < array.length; i++) { + array[i] = createValue(valueClass.getComponentType(), processedTypes); + } + return array; + } + + private Object createMap(ParameterizedType type, FList<Type> processedTypes) throws Exception { + Type keyType = type.getActualTypeArguments()[0]; + Type valueType = type.getActualTypeArguments()[1]; + final HashMap<Object, Object> map = new HashMap<Object, Object>(); + for (int i = 0; i < 2; i++) { + Object key = createValue(keyType, processedTypes); + Object value = createValue(valueType, processedTypes); + if (key != null && value != null) { + map.put(key, value); + } + } + return map; + } + + @Nullable + private Object createCollection(Class<?> aClass, ParameterizedType genericType, FList<Type> processedTypes) throws Exception { + final Type elementClass = genericType.getActualTypeArguments()[0]; + Collection<Object> o; + if (List.class.isAssignableFrom(aClass)) { + o = new ArrayList<Object>(); + } + else if (Set.class.isAssignableFrom(aClass)) { + o = new HashSet<Object>(); + } + else { + return null; + } + for (int i = 0; i < 2; i++) { + final Object item = createValue(elementClass, processedTypes); + if (item != null) { + o.add(item); + } + } + return o; + } + } +} |