vcs: Moved several classes to [svn4idea]
[idea/community.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / branchConfig / SvnLoadedBranchesStorage.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.idea.svn.branchConfig;
17
18 import com.intellij.openapi.application.PathManager;
19 import com.intellij.openapi.project.Project;
20 import org.jetbrains.idea.svn.SmallMapSerializer;
21 import com.intellij.openapi.vfs.VirtualFile;
22 import com.intellij.util.containers.ContainerUtil;
23 import com.intellij.util.io.DataExternalizer;
24 import com.intellij.util.io.EnumeratorStringDescriptor;
25 import org.jetbrains.annotations.NotNull;
26 import org.jetbrains.annotations.Nullable;
27
28 import java.io.DataInput;
29 import java.io.DataOutput;
30 import java.io.File;
31 import java.io.IOException;
32 import java.util.*;
33
34 /**
35  * Created by IntelliJ IDEA.
36  * User: Irina.Chernushina
37  * Date: 8/24/11
38  * Time: 1:21 PM
39  */
40 public class SvnLoadedBranchesStorage {
41   private final Object myLock;
42   private SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>> myState;
43   private final File myFile;
44   private final Project myProject;
45
46   public SvnLoadedBranchesStorage(final Project project) {
47     myProject = project;
48     final File vcsFile = new File(PathManager.getSystemPath(), "vcs");
49     File file = new File(vcsFile, "svn_branches");
50     file.mkdirs();
51     myFile = new File(file, project.getLocationHash());
52     myLock = new Object();
53   }
54   
55   @Nullable
56   public Collection<SvnBranchItem> get(final String url) {
57     synchronized (myLock) {
58       if (myState == null) return null;
59       Map<String, Collection<SvnBranchItem>> map = myState.get("");
60       return map == null ? null : map.get(SvnBranchConfigurationNew.ensureEndSlash(url));
61     }
62   }
63   
64   public void activate() {
65     synchronized (myLock) {
66       myState = new SmallMapSerializer<>(myFile, EnumeratorStringDescriptor.INSTANCE, createExternalizer());
67     }
68   }
69
70
71   public void deactivate() {
72     Map<String, Collection<SvnBranchItem>> branchLocationToBranchItemsMap = ContainerUtil.newHashMap();
73     SvnBranchConfigurationManager manager = SvnBranchConfigurationManager.getInstance(myProject);
74     Map<VirtualFile,SvnBranchConfigurationNew> mapCopy = manager.getSvnBranchConfigManager().getMapCopy();
75     for (Map.Entry<VirtualFile, SvnBranchConfigurationNew> entry : mapCopy.entrySet()) {
76       Map<String,InfoStorage<List<SvnBranchItem>>> branchMap = entry.getValue().getBranchMap();
77       for (Map.Entry<String, InfoStorage<List<SvnBranchItem>>> storageEntry : branchMap.entrySet()) {
78         branchLocationToBranchItemsMap.put(storageEntry.getKey(), storageEntry.getValue().getValue());
79       }
80     }
81     synchronized (myLock) {
82       // TODO: Possibly implement optimization - do not perform save if there are no changes in branch locations and branch items
83       // ensure myState.put() is called - so myState will treat itself as dirty and myState.force() will invoke real persisting
84       myState.put("", branchLocationToBranchItemsMap);
85       myState.force();
86       myState = null;
87     }
88   }
89
90   private DataExternalizer<Map<String, Collection<SvnBranchItem>>> createExternalizer() {
91     return new DataExternalizer<Map<String, Collection<SvnBranchItem>>>() {
92       @Override
93       public void save(@NotNull DataOutput out, Map<String, Collection<SvnBranchItem>> value) throws IOException {
94         out.writeInt(value.size());
95         ArrayList<String> keys = new ArrayList<>(value.keySet());
96         Collections.sort(keys);
97         for (String key : keys) {
98           out.writeUTF(key);
99           List<SvnBranchItem> list = new ArrayList<>(value.get(key));
100           Collections.sort(list, SerializationComparator.getInstance());
101           out.writeInt(list.size());
102           for (SvnBranchItem item : list) {
103             out.writeUTF(item.getUrl());
104             out.writeLong(item.getCreationDateMillis());
105             out.writeLong(item.getRevision());
106           }
107         }
108       }
109
110       @Override
111       public Map<String, Collection<SvnBranchItem>> read(@NotNull DataInput in) throws IOException {
112         final HashMap<String, Collection<SvnBranchItem>> map = new HashMap<>();
113         int mapSize = in.readInt();
114         for (int i = 0; i < mapSize; i++) {
115           final String key = in.readUTF();
116           final int size = in.readInt();
117           final ArrayList<SvnBranchItem> list = new ArrayList<>(size);
118           for (int j = 0; j < size; j++) {
119             String url = in.readUTF();
120             long creation = in.readLong();
121             long revision = in.readLong();
122             list.add(new SvnBranchItem(url, new Date(creation), revision));
123           }
124           map.put(key, list);
125         }
126         return map;
127       }
128     };
129   }
130   
131   private static class SerializationComparator implements Comparator<SvnBranchItem> {
132     private final static SerializationComparator ourInstance = new SerializationComparator();
133     
134     public static SerializationComparator getInstance() {
135       return ourInstance;
136     }
137     
138     @Override
139     public int compare(SvnBranchItem o1, SvnBranchItem o2) {
140       return o1.getUrl().compareToIgnoreCase(o2.getUrl());
141     }
142   }
143 }