1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package eu.ehri.project.tools;
21
22 import com.google.common.collect.Lists;
23 import com.tinkerpop.frames.FramedGraph;
24 import eu.ehri.project.acl.SystemScope;
25 import eu.ehri.project.core.GraphManager;
26 import eu.ehri.project.core.GraphManagerFactory;
27 import eu.ehri.project.definitions.Ontology;
28 import eu.ehri.project.exceptions.SerializationError;
29 import eu.ehri.project.models.EntityClass;
30 import eu.ehri.project.models.base.Accessible;
31 import eu.ehri.project.models.base.Described;
32 import eu.ehri.project.models.base.Description;
33 import eu.ehri.project.models.base.Entity;
34 import eu.ehri.project.models.base.PermissionScope;
35 import eu.ehri.project.models.base.Versioned;
36 import eu.ehri.project.models.events.Version;
37 import eu.ehri.project.models.idgen.IdGenerator;
38 import eu.ehri.project.persistence.Bundle;
39 import eu.ehri.project.persistence.Serializer;
40
41 import java.util.Collection;
42 import java.util.List;
43 import java.util.Optional;
44
45
46
47
48
49
50
51
52
53
54
55
56 public class IdRegenerator {
57 private final FramedGraph<?> graph;
58 private final GraphManager manager;
59 private final Serializer depSerializer;
60 private final boolean dryrun;
61 private final boolean skipCollisions;
62 private final boolean collisionMode;
63
64 public static class IdCollisionError extends Exception {
65 IdCollisionError(String from, String to) {
66 super(String.format("Renaming %s to %s would collide with existing item",
67 from, to));
68 }
69 }
70
71 public IdRegenerator(FramedGraph<?> graph) {
72 this(graph, true, false, false);
73 }
74
75 private IdRegenerator(FramedGraph<?> graph, boolean dryrun, boolean skipCollisions,
76 boolean collisionMode) {
77 this.graph = graph;
78 this.manager = GraphManagerFactory.getInstance(graph);
79 this.depSerializer = new Serializer.Builder(graph).dependentOnly().build();
80 this.dryrun = dryrun;
81 this.skipCollisions = skipCollisions;
82 this.collisionMode = collisionMode;
83 }
84
85 public List<List<String>> reGenerateIds(PermissionScope scope, Iterable<? extends Entity> items) throws
86 IdCollisionError {
87 List<List<String>> remaps = Lists.newArrayList();
88 for (Entity item : items) {
89 Optional<List<String>> optionalRemap = reGenerateId(scope, item);
90 optionalRemap.ifPresent(remaps::add);
91 }
92 return remaps;
93 }
94
95 public List<List<String>> reGenerateIds(Iterable<? extends Accessible> items) throws IdCollisionError {
96 List<List<String>> remaps = Lists.newArrayList();
97 for (Accessible item : items) {
98 Optional<List<String>> optionalRemap = reGenerateId(item);
99 optionalRemap.ifPresent(remaps::add);
100 }
101 return remaps;
102 }
103
104 public Optional<List<String>> reGenerateId(Accessible item) throws IdCollisionError {
105 return reGenerateId(item.getPermissionScope(), item);
106 }
107
108 Optional<List<String>> reGenerateId(PermissionScope permissionScope, Entity item)
109 throws IdCollisionError {
110 String currentId = item.getId();
111 Collection<String> idChain = Lists.newArrayList();
112 if (permissionScope != null && !permissionScope.equals(SystemScope.getInstance())) {
113 idChain.addAll(permissionScope.idPath());
114 }
115
116 EntityClass entityClass = manager.getEntityClass(item);
117 try {
118 IdGenerator idgen = entityClass.getIdGen();
119 Bundle itemBundle = depSerializer.entityToBundle(item);
120 String newId = idgen.generateId(idChain, itemBundle);
121 if (collisionMode) {
122 if (!newId.equals(currentId) && manager.exists(newId)) {
123 List<String> collision = Lists.newArrayList(currentId, newId);
124 return Optional.of(collision);
125 } else {
126 return Optional.empty();
127 }
128 } else {
129 if (!newId.equals(currentId)) {
130 if (manager.exists(newId)) {
131 if (!skipCollisions) {
132 throw new IdCollisionError(currentId, newId);
133 } else {
134 return Optional.empty();
135 }
136 } else {
137 if (!dryrun) {
138 manager.renameVertex(item.asVertex(), currentId, newId);
139
140
141 String idBase = idgen.getIdBase(itemBundle);
142 Collection<String> descIdChain = Lists.newArrayList(idChain);
143 descIdChain.add(idBase);
144 for (Description d : item.as(Described.class).getDescriptions()) {
145 Bundle desc = depSerializer.entityToBundle(d);
146 String newDescriptionId = desc.getType().getIdGen().generateId(descIdChain, desc);
147 manager.renameVertex(d.asVertex(), d.getId(), newDescriptionId);
148 }
149
150
151 for (Version v : item.as(Versioned.class).getAllPriorVersions()) {
152 manager.setProperty(v.asVertex(), Ontology.VERSION_ENTITY_ID, newId);
153 }
154 }
155 List<String> remap = Lists.newArrayList(currentId, newId);
156 return Optional.of(remap);
157 }
158 } else {
159 return Optional.empty();
160 }
161 }
162 } catch (SerializationError e) {
163 throw new RuntimeException(e);
164 }
165 }
166
167
168
169
170
171
172
173
174 public IdRegenerator withActualRename(boolean doIt) {
175 return new IdRegenerator(graph, !doIt, skipCollisions, collisionMode);
176 }
177
178
179
180
181
182
183
184
185 public IdRegenerator skippingCollisions(boolean skipCollisions) {
186 return new IdRegenerator(graph, dryrun, skipCollisions, collisionMode);
187 }
188
189
190
191
192
193
194
195
196 public IdRegenerator collisionMode(boolean collisionMode) {
197 return new IdRegenerator(graph, dryrun, skipCollisions, collisionMode);
198 }
199 }