blob: 977d85ed21bfdca4d6d482dddf385f43ec0d05a5 [file] [log] [blame]
/*
* Copyright 2000-2014 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 com.intellij.profile;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.StateSplitter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.UniqueNameGenerator;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* User: anna
* Date: 30-Nov-2005
*/
public abstract class DefaultProjectProfileManager extends ProjectProfileManager implements JDOMExternalizable {
protected static final Logger LOG = Logger.getInstance("#com.intellij.profile.DefaultProjectProfileManager");
@NonNls protected static final String PROFILES = "profiles";
@NonNls public static final String SCOPES = "scopes";
@NonNls protected static final String SCOPE = "scope";
@NonNls public static final String PROFILE = "profile";
@NonNls protected static final String NAME = "name";
private static final String VERSION = "1.0";
@NotNull
protected final Project myProject;
/** This field is used for serialization. Do not rename it or make access weaker */
public String PROJECT_PROFILE;
/** This field is used for serialization. Do not rename it or make access weaker */
public boolean USE_PROJECT_PROFILE = true;
private final ApplicationProfileManager myApplicationProfileManager;
private final Map<String, Profile> myProfiles = new HashMap<String, Profile>();
protected final DependencyValidationManager myHolder;
private final List<ProfileChangeAdapter> myProfilesListener = ContainerUtil.createLockFreeCopyOnWriteList();
@NonNls private static final String PROJECT_DEFAULT_PROFILE_NAME = "Project Default";
public DefaultProjectProfileManager(@NotNull final Project project,
@NotNull ApplicationProfileManager applicationProfileManager,
@NotNull DependencyValidationManager holder) {
myProject = project;
myHolder = holder;
myApplicationProfileManager = applicationProfileManager;
}
@NotNull
public Project getProject() {
return myProject;
}
@Override
public synchronized Profile getProfile(@NotNull String name, boolean returnRootProfileIfNamedIsAbsent) {
return myProfiles.containsKey(name) ? myProfiles.get(name) : myApplicationProfileManager.getProfile(name, returnRootProfileIfNamedIsAbsent);
}
@Override
public synchronized void updateProfile(@NotNull Profile profile) {
myProfiles.put(profile.getName(), profile);
for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
profileChangeAdapter.profileChanged(profile);
}
}
@Override
public synchronized void readExternal(Element element) throws InvalidDataException {
myProfiles.clear();
DefaultJDOMExternalizer.readExternal(this, element);
final Element profilesElement = element.getChild(PROFILES);
if (profilesElement != null) {
for (Object o : profilesElement.getChildren(PROFILE)) {
final Profile profile = myApplicationProfileManager.createProfile();
profile.setProfileManager(this);
profile.readExternal((Element)o);
final String name = profile.getName();
if (myApplicationProfileManager.getProfile(name) != null) { //override ide profile
// myApplicationProfileManager.deleteProfile(name);
}
myProfiles.put(name, profile);
}
}
if (element.getChild("version") == null || !Comparing.strEqual(element.getChild("version").getAttributeValue("value"), VERSION)) {
boolean toConvert = true;
for (Object o : element.getChildren("option")) {
if (Comparing.strEqual(((Element)o).getAttributeValue("name"), "USE_PROJECT_LEVEL_SETTINGS")) {
toConvert = Boolean.parseBoolean(((Element)o).getAttributeValue("value"));
break;
}
}
if (toConvert) {
convert(element);
}
}
}
protected void convert(Element element) throws InvalidDataException {
}
@Override
public synchronized void writeExternal(Element element) throws WriteExternalException {
final List<String> sortedProfiles = new ArrayList<String>(myProfiles.keySet());
Collections.sort(sortedProfiles);
Element profiles = null;
for (String profile : sortedProfiles) {
final Profile projectProfile = myProfiles.get(profile);
if (projectProfile != null) {
final Element profileElement = new Element(PROFILE);
projectProfile.writeExternal(profileElement);
boolean hasSmthToSave = sortedProfiles.size() > 1 || isDefaultProfileUsed();
if (!hasSmthToSave) {
for (Object child : profileElement.getChildren()) {
if (!((Element)child).getName().equals("option")) {
hasSmthToSave = true;
break;
}
}
}
if (!hasSmthToSave) continue;
if (profiles == null) {
profiles = new Element(PROFILES);
element.addContent(profiles);
}
profiles.addContent(profileElement);
}
}
if (profiles != null || isDefaultProfileUsed()) {
DefaultJDOMExternalizer.writeExternal(this, element);
final Element version = new Element("version");
version.setAttribute("value", VERSION);
element.addContent(version);
}
}
private boolean isDefaultProfileUsed() {
return PROJECT_PROFILE != null && !Comparing.strEqual(PROJECT_PROFILE, PROJECT_DEFAULT_PROFILE_NAME);
}
@NotNull
@Override
public NamedScopesHolder getScopesManager() {
return myHolder;
}
@NotNull
@Override
public synchronized Collection<Profile> getProfiles() {
getProjectProfileImpl();
return myProfiles.values();
}
@NotNull
@Override
public synchronized String[] getAvailableProfileNames() {
return ArrayUtil.toStringArray(myProfiles.keySet());
}
@Override
public synchronized void deleteProfile(String name) {
myProfiles.remove(name);
}
@Override
public synchronized String getProjectProfile() {
return PROJECT_PROFILE;
}
@Override
public synchronized void setProjectProfile(@Nullable final String newProfile) {
final String oldProfile = PROJECT_PROFILE;
PROJECT_PROFILE = newProfile;
USE_PROJECT_PROFILE = newProfile != null;
if (oldProfile != null) {
for (ProfileChangeAdapter adapter : myProfilesListener) {
adapter.profileActivated(getProfile(oldProfile), newProfile != null ? getProfile(newProfile) : null);
}
}
}
@NotNull
public synchronized Profile getProjectProfileImpl(){
if (!USE_PROJECT_PROFILE) return myApplicationProfileManager.getRootProfile();
if (PROJECT_PROFILE == null || myProfiles.isEmpty()){
setProjectProfile(PROJECT_DEFAULT_PROFILE_NAME);
final Profile projectProfile = myApplicationProfileManager.createProfile();
projectProfile.copyFrom(myApplicationProfileManager.getRootProfile());
projectProfile.setLocal(false);
projectProfile.setName(PROJECT_DEFAULT_PROFILE_NAME);
myProfiles.put(PROJECT_DEFAULT_PROFILE_NAME, projectProfile);
}
else if (!myProfiles.containsKey(PROJECT_PROFILE)){
final String projectProfileAttempt = myProfiles.keySet().iterator().next();
setProjectProfile(projectProfileAttempt);
}
final Profile profile = myProfiles.get(PROJECT_PROFILE);
profile.setProfileManager(this);
return profile;
}
public void addProfilesListener(@NotNull final ProfileChangeAdapter profilesListener, @NotNull Disposable parent) {
myProfilesListener.add(profilesListener);
Disposer.register(parent, new Disposable() {
@Override
public void dispose() {
myProfilesListener.remove(profilesListener);
}
});
}
public void removeProfilesListener(@NotNull ProfileChangeAdapter profilesListener) {
myProfilesListener.remove(profilesListener);
}
public static class ProfileStateSplitter implements StateSplitter {
@Override
public List<Pair<Element, String>> splitState(final Element e) {
final UniqueNameGenerator generator = new UniqueNameGenerator();
List<Pair<Element, String>> result = new ArrayList<Pair<Element, String>>();
final Element[] elements = JDOMUtil.getElements(e);
for (Element element : elements) {
if (element.getName().equals("profiles")) {
element.detach();
final Element[] profiles = JDOMUtil.getElements(element);
for (Element profile : profiles) {
String profileName = null;
final Element[] options = JDOMUtil.getElements(profile);
for (Element option : options) {
if (option.getName().equals("option") && option.getAttributeValue("name").equals("myName")) {
profileName = option.getAttributeValue("value");
}
}
assert profileName != null;
final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(profileName)) + ".xml";
result.add(Pair.create(profile, name));
}
}
}
if (!e.getContent().isEmpty()) result.add(Pair.create(e, generator.generateUniqueName("profiles_settings") + ".xml"));
return result;
}
@Override
public void mergeStatesInto(final Element target, final Element[] elements) {
Element profiles = new Element("profiles");
target.addContent(profiles);
for (Element element : elements) {
if (element.getName().equals("profile")) {
element.detach();
profiles.addContent(element);
}
else {
final Element[] states = JDOMUtil.getElements(element);
for (Element state : states) {
state.detach();
target.addContent(state);
}
}
}
}
}
protected void fireProfilesInitialized() {
for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
profileChangeAdapter.profilesInitialized();
}
}
protected void fireProfilesShutdown() {
for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
profileChangeAdapter.profilesShutdown();
}
}
}