/*
* Copyright 2003-2011 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 jetbrains.mps.plugins.projectplugins;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.HashMap;
import com.intellij.util.xmlb.annotations.Tag;
import jetbrains.mps.ide.ThreadUtils;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.ide.tools.BaseTool;
import jetbrains.mps.plugins.custom.BaseCustomProjectPlugin;
import jetbrains.mps.plugins.prefs.BaseProjectPrefsComponent;
import jetbrains.mps.plugins.relations.RelationDescriptor;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.plugins.tool.BaseGeneratedTool;
import jetbrains.mps.plugins.projectplugins.BaseProjectPlugin.PluginState;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.module.ModelAccess;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public abstract class BaseProjectPlugin implements PersistentStateComponent<PluginState> {
private static final Logger LOG = LogManager.getLogger(BaseProjectPlugin.class);
private Project myProject;
private List<BaseTool> myTools = new ArrayList<BaseTool>();
private EDTAccessor<List<BaseTool>> myInitializedTools = new EDTAccessor<List<BaseTool>>(new ArrayList<BaseTool>());
private List<BaseCustomProjectPlugin> myCustomPlugins = new ArrayList<BaseCustomProjectPlugin>();
private List<BaseProjectPrefsComponent> myPrefsComponents = new ArrayList<BaseProjectPrefsComponent>();
private List<RelationDescriptor> myTabDescriptors = new ArrayList<RelationDescriptor>();
public Project getProject() {
return myProject;
}
//------------------stuff to generate-----------------------
protected List<RelationDescriptor> initTabbedEditors(Project project) {
return new ArrayList<RelationDescriptor>();
}
//remove after 3.3
protected List<BaseGeneratedTool> initAllTools(Project project) {
return new ArrayList<BaseGeneratedTool>();
}
protected List<BaseTool> initAllTools1(Project project) {
return new ArrayList<BaseTool>();
}
protected List<BaseProjectPrefsComponent> createPreferencesComponents(Project project) {
return new ArrayList<BaseProjectPrefsComponent>();
}
protected List<BaseCustomProjectPlugin> initCustomParts(Project project) {
return new ArrayList<BaseCustomProjectPlugin>();
}
@NotNull
private ModelAccess getModelAccess() {
ModelAccess modelAccess = ProjectHelper.getModelAccess(myProject);
assert modelAccess != null;
return modelAccess;
}
public final void init(@NotNull final Project project) {
myProject = project;
initTabbedEditors1(project);
initCustomParts1(project);
initTools1();
createPrefComponents1();
registerPrefsAndTools();
}
private void createPrefComponents1() {
try {
myPrefsComponents = createPreferencesComponents(myProject);
} catch (Throwable t) {
LOG.error("Exception on project preference components init:", t);
}
}
protected void initTools1() {
try {
myTools.addAll(initAllTools(myProject));
myTools.addAll(initAllTools1(myProject));
} catch (Throwable t) {
LOG.error("Exception on tools init:", t);
}
}
protected void initTabbedEditors1(Project project) {
try {
myTabDescriptors = initTabbedEditors(project);
} catch (Throwable t) {
LOG.error("Exception on tabbed editors init:", t);
}
}
protected void initCustomParts1(Project project) {
try {
myCustomPlugins = initCustomParts(project);
} catch (Throwable t) {
LOG.error("Exception on custom project plugins init:", t);
}
}
private void registerPrefsAndTools() {
final List<BaseTool> toolsToInit = new ArrayList<BaseTool>(myTools);
final List<BaseProjectPrefsComponent> prefsToInit = new ArrayList<BaseProjectPrefsComponent>(myPrefsComponents);
for (BaseTool tool : toolsToInit) {
try {
tool.init(myProject);
tool.register();
} catch (Throwable t) {
LOG.error("Exception on a tool init: " + tool, t);
}
myInitializedTools.get().add(tool);
}
for (BaseProjectPrefsComponent component : prefsToInit) {
try {
component.init();
} catch (Throwable t) {
LOG.error("Exception on a pref component init: " + component, t);
}
}
}
public final void dispose() {
disposePrefsToolsAndCustomParts();
disposeTabbedEditors();
}
private void disposeTabbedEditors() {
myTabDescriptors.clear();
}
private void disposePrefsToolsAndCustomParts() {
disposePrefComponents(myPrefsComponents);
disposeTools(myTools);
disposeCustomPlugins(myCustomPlugins);
myPrefsComponents.clear();
myTools.clear();
myCustomPlugins.clear();
}
private void disposeCustomPlugins(final List<BaseCustomProjectPlugin> customPluginsToDispose) {
for (BaseCustomProjectPlugin customPlugin : customPluginsToDispose) {
try {
customPlugin.dispose();
} catch (Throwable t) {
LOG.error("Exception on the custom project plugin component dispose: " + customPlugin, t);
}
}
}
private void disposeTools(List<BaseTool> toolsToDispose) {
for (BaseTool tool : toolsToDispose) {
if (myInitializedTools.get().contains(tool)) {
try {
tool.unregister();
tool.dispose();
} catch (Throwable t) {
LOG.error("Exception on a tool dispose: " + tool, t);
} finally {
myInitializedTools.get().remove(tool);
}
}
}
}
private void disposePrefComponents(List<BaseProjectPrefsComponent> prefsComponentsToDispose) {
for (BaseProjectPrefsComponent component : prefsComponentsToDispose) {
try {
component.dispose();
} catch (Throwable t) {
LOG.error("Exception on a project preference component dispose: " + component, t);
}
}
}
//------------------tools stuff-----------------------
public List<BaseProjectPrefsComponent> getPrefsComponents() {
return Collections.unmodifiableList(myPrefsComponents);
}
public List<BaseTool> getTools() {
return Collections.unmodifiableList(myTools);
}
public List<RelationDescriptor> getTabDescriptors() {
return Collections.unmodifiableList(myTabDescriptors);
}
//----------------STATE STUFF------------------------
@Override
public PluginState getState() {
PluginState state = new PluginState();
for (BaseProjectPrefsComponent component : myPrefsComponents) {
try {
Element componentState = component.getState();
state.myComponentsState.add(new ComponentState(component.getClass().getName(), componentState));
} catch (Throwable t) {
LOG.error("", t);
}
}
return state;
}
@Override
public void loadState(PluginState state) {
HashMap<String, BaseProjectPrefsComponent> components = new HashMap<String, BaseProjectPrefsComponent>();
for (BaseProjectPrefsComponent component : myPrefsComponents) {
components.put(component.getClass().getName(), component);
}
for (ComponentState componentState : state.myComponentsState) {
if (componentState.second == null) return;
try {
BaseProjectPrefsComponent component = components.get(componentState.first);
if (component != null) {
component.loadState(componentState.second);
}
} catch (Throwable t) {
LOG.error("", t);
}
}
}
public static class PluginState {
public List<ComponentState> myComponentsState = new ArrayList<ComponentState>();
}
public static class ComponentState {
public String first;
@Tag(value = "params")
public Element second;
public ComponentState() {
}
public ComponentState(String first, Element second) {
this.first = first;
this.second = second;
}
}
private static class EDTAccessor<T> {
private T myT;
public EDTAccessor(T t) {
myT = t;
}
public T get() {
ThreadUtils.assertEDT();
return myT;
}
}
}