/*
* 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.openapi.components.impl.stores;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.StateStorage.SaveSession;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.project.impl.ProjectManagerImpl;
import com.intellij.openapi.util.Couple;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class DefaultProjectStoreImpl extends ProjectStoreImpl {
private final ProjectManagerImpl myProjectManager;
@NonNls private static final String ROOT_TAG_NAME = "defaultProject";
public DefaultProjectStoreImpl(@NotNull ProjectImpl project, @NotNull ProjectManagerImpl projectManager, @NotNull PathMacroManager pathMacroManager) {
super(project, pathMacroManager);
myProjectManager = projectManager;
}
@Nullable
Element getStateCopy() {
final Element element = myProjectManager.getDefaultProjectRootElement();
return element != null ? element.clone() : null;
}
@NotNull
@Override
protected StateStorageManager createStateStorageManager() {
final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, myPathMacroManager.createTrackingSubstitutor(),
ROOT_TAG_NAME, null) {
@Override
@Nullable
protected Element loadLocalData() {
return myProjectManager.getDefaultProjectRootElement();
}
@Override
protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) {
return new XmlElementStorageSaveSession(storageData) {
@Override
protected void doSave(@Nullable Element element) {
// we must set empty element instead of null as indicator - ProjectManager state is ready to save
myProjectManager.setDefaultProjectRootElement(element == null ? new Element("empty") : element);
}
// we must not collapse paths here, because our solution is just a big hack
// by default, getElementToSave() returns collapsed paths -> setDefaultProjectRootElement -> project manager writeExternal -> save -> compare old and new - diff because old has expanded, but new collapsed
// -> needless save
@Override
protected boolean isCollapsePathsOnSave() {
return false;
}
};
}
@Override
@NotNull
protected StorageData createStorageData() {
return new StorageData(ROOT_TAG_NAME);
}
};
//noinspection deprecation
return new StateStorageManager() {
@Override
public void addMacro(@NotNull String macro, @NotNull String expansion) {
throw new UnsupportedOperationException("Method addMacro not implemented in " + getClass());
}
@Override
@Nullable
public TrackingPathMacroSubstitutor getMacroSubstitutor() {
return null;
}
@Override
@Nullable
public StateStorage getStateStorage(@NotNull Storage storageSpec) throws StateStorageException {
return storage;
}
@Nullable
@Override
public StateStorage getStateStorage(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
return storage;
}
@NotNull
@Override
public Couple<Collection<FileBasedStorage>> getCachedFileStateStorages(@NotNull Collection<String> changed, @NotNull Collection<String> deleted) {
return new Couple<>(Collections.<FileBasedStorage>emptyList(), Collections.<FileBasedStorage>emptyList());
}
@Override
public void clearStateStorage(@NotNull String file) {
}
@Nullable
@Override
public ExternalizationSession startExternalization() {
StateStorage.ExternalizationSession externalizationSession = storage.startExternalization();
return externalizationSession == null ? null : new MyExternalizationSession(externalizationSession);
}
@NotNull
@Override
public String expandMacros(@NotNull String file) {
throw new UnsupportedOperationException("Method expandMacros not implemented in " + getClass());
}
@NotNull
@Override
public String collapseMacros(@NotNull String path) {
throw new UnsupportedOperationException("Method collapseMacros not implemented in " + getClass());
}
@Override
public void setStreamProvider(@Nullable StreamProvider streamProvider) {
throw new UnsupportedOperationException("Method setStreamProvider not implemented in " + getClass());
}
@Nullable
@Override
public StreamProvider getStreamProvider() {
throw new UnsupportedOperationException("Method getStreamProviders not implemented in " + getClass());
}
@NotNull
@Override
public Collection<String> getStorageFileNames() {
throw new UnsupportedOperationException("Method getStorageFileNames not implemented in " + getClass());
}
};
}
@Override
public void load() throws IOException {
if (myProjectManager.getDefaultProjectRootElement() != null) {
super.load();
}
}
private static class MyExternalizationSession implements StateStorageManager.ExternalizationSession {
@NotNull final StateStorage.ExternalizationSession externalizationSession;
public MyExternalizationSession(@NotNull StateStorage.ExternalizationSession externalizationSession) {
this.externalizationSession = externalizationSession;
}
@Override
public void setState(@NotNull Storage[] storageSpecs, @NotNull Object component, @NotNull String componentName, @NotNull Object state) {
externalizationSession.setState(component, componentName, state, null);
}
@NotNull
@Override
public List<SaveSession> createSaveSessions() {
return ContainerUtil.createMaybeSingletonList(externalizationSession.createSaveSession());
}
}
}