Project

General

Profile

1
package gr.uoa.di.web.utils.ep;
2

    
3

    
4
//import eu.dnetlib.api.data.PublisherService;
5
import eu.dnetlib.api.data.PublisherService;
6
import eu.dnetlib.api.data.PublisherServiceException;
7
import eu.dnetlib.domain.data.Document;
8
import eu.dnetlib.domain.functionality.UserProfile;
9
import gr.uoa.di.driver.util.ServiceLocator;
10
import gr.uoa.di.web.utils.ep.domain.Edge;
11
import gr.uoa.di.web.utils.ep.domain.*;
12
import gr.uoa.di.web.utils.ep.domain.Graph;
13
import gr.uoa.di.web.utils.ep.domain.Node;
14
import gr.uoa.di.web.utils.ep.domain.RelatedNode;
15
import gr.uoa.di.web.utils.search.DocumentPage;
16
import gr.uoa.di.web.utils.search.DocumentReader;
17
import org.apache.log4j.Logger;
18

    
19
import java.io.UnsupportedEncodingException;
20
import java.net.URLDecoder;
21
import java.util.*;
22

    
23
public class EPManagerMock implements EPManager {
24
	private static final String FORMAT = "DMF";
25
	private static final String COMMAND = "command";
26
	private static final String CREATE = "create";
27
	private static final String IMPORT = "import";
28
	private static final String EDIT = "edit";
29
	private static final String DELETE ="delete";
30
	private static final String ADD = "add";
31
	private static final String REMOVE = "remove";
32
	private static final String ID = "id";
33
	private static final String ENTITY = "entity";
34
	private static final String RELATION = "relation";
35
	private static final String SOURCE = "source";
36
	private static final String TARGET = "target";
37
	private static final String DOCUMENT_PREFIX = "document.";
38
	private static final String PARAMETER_DELIMITER = "&";
39
	private static final String UTF8 = "utf8";
40
	private static final String VALUE_DELIMITER = "=";
41
	private static final String USER_PLACEHOLDER = "$user";
42
	private static final String TEMP_ID_PREFIX = "temporaryId";
43
	
44
	private static Logger logger = Logger.getLogger(EPManagerMock.class);
45
	
46
	private ServiceLocator<PublisherService> publisherServiceLocator;
47
	private DocumentReader documentReader;
48
	private Field description;
49
	private Field language;
50
	private Field subject;
51
	private Field title;
52
	private Entity aggregationObjects;
53
	private Entity ePrints;
54
	private Entity ePubs;
55
	private Entity nonEPrints;
56
	private Relation aggregates;
57
	private Relation composedBy;
58
	private Relation hasEPrint;
59
	private Set<Entity> entities;
60
	private Set<Relation> relations;
61
	private Graph graph;
62
	private Map<String, Map<String, String>> temporaryIds;
63
	
64
	@SuppressWarnings("unchecked")
65
	public EPManagerMock() {
66
		Field cObjCategory = new Field("CobjCategory", "Compound Object Category", false, false, null);
67
		Field cObjContentSynthesis = new Field("CobjContentSynthesis", "Compound Object Content Synthesis", false, false, null);
68
		Field cObjDescriptionSynthesis = new Field("CobjDescriptionSynthesis", "Compound Object Description Synthesis", false, false, null);
69
		Field cObjIdentifier = new Field("id", "Compound Object Identifier", false, false, null);
70
		Field cObjMDFormats = new Field("CobjMDFormats", "Compound Object Metadata Formats", false, false, null);
71
		Field cObjModel = new Field("CobjModel", "Compound Object Model", false, false, null);
72
		Field cObjTypologyCompoundObject = new Field("CobjTypology", "Compound Object Typology", false, false, "Compound Object");
73
		Field cObjTypologyTextual = new Field("CobjTypology", "Compound Object Typology", false, false, "Textual");
74
		Field cObjTypologyDataSet = new Field("CobjTypology", "Compound Object Typology", false, false, "Data Set");
75
		Field contributor = new Field("contributor", "Contributor", true, false, null);
76
		Field creator = new Field("creator", "Creator", true, false, "$user");
77
		Field dateAccepted = new Field("dateAccepted", "Date Accepted", false, false, null);
78
		Field dateOfCollection = new Field("dateOfCollection", "Date Of Collection", false, false, null);
79
		description = new Field("description", "Description", false, true, null);
80
		Field identifier = new Field("identifier", "Identifier", false, false, null);
81
		Field itemIdentifier = new Field("itemIdentifier", "Item Identifier", false, false, null);
82
		language = new Field("language", "Language", false, true, null);
83
		Field mdFormat = new Field("mdFormat", "Metadata Format", false, false, "DMF");
84
		Field mdFormatInterpretation = new Field("mdFormatInterpretation", "Metadata Format Interpretation", false, false, null);
85
		Field objIdentifier = new Field("objIdentifier", "Object Identifier", false, false, null);
86
		Field objectIdentifier = new Field("objectIdentifier", "Object Identifier", false, false, null);
87
		Field publisher = new Field("publisher", "Publisher", false, false, null);
88
		Field recordIdentifier = new Field("recordIdentifier", "Record Identifier", false, false, null);
89
		Field relation = new Field("relation", "Relation", true, false, null);
90
		Field repositoryCountry = new Field("repositoryCountry", "Repository Country", false, false, null);
91
		Field repositoryId = new Field("repositoryId", "Repository Identifier", false, false, null);
92
		Field repositoryInstitution = new Field("repositoryInstitution", "RepositoryInstitution", false, false, "Driver");
93
		Field repositoryLink = new Field("repositoryLink", "Repository Link", false, false, "http://search.driver.research-infrastructures.eu/");
94
		Field repositoryName = new Field("repositoryName", "Repository Name", false, false, "Driver");
95
		Field source = new Field("source", "Source", false, false, null);
96
		subject = new Field("subject", "Subject", true, true, null);
97
		title = new Field("title", "Title", true, true, null);
98
		Field sequenceNo = new Field("sequenceNo", "Sequence Number", false, true, null);
99
		
100
		Set<Field> commonFields = new HashSet<Field>();
101
		commonFields.add(cObjCategory);
102
		commonFields.add(cObjContentSynthesis);
103
		commonFields.add(cObjDescriptionSynthesis);
104
		commonFields.add(cObjIdentifier);
105
		commonFields.add(cObjMDFormats);
106
		commonFields.add(cObjModel);
107
		commonFields.add(contributor);
108
		commonFields.add(creator);
109
		commonFields.add(dateAccepted);
110
		commonFields.add(dateOfCollection);
111
		commonFields.add(description);
112
		commonFields.add(identifier);
113
		commonFields.add(itemIdentifier);
114
		commonFields.add(language);
115
		commonFields.add(mdFormat);
116
		commonFields.add(mdFormatInterpretation);
117
		commonFields.add(objIdentifier);
118
		commonFields.add(objectIdentifier);
119
		commonFields.add(publisher);
120
		commonFields.add(recordIdentifier);
121
		commonFields.add(relation);
122
		commonFields.add(repositoryCountry);
123
		commonFields.add(repositoryId);
124
		commonFields.add(repositoryInstitution);
125
		commonFields.add(repositoryLink);
126
		commonFields.add(repositoryName);
127
		commonFields.add(source);
128
		commonFields.add(subject);
129
		commonFields.add(title);
130
		
131
		Set<Field> compoundObjectFields = new HashSet<Field>(commonFields);
132
		compoundObjectFields.add(cObjTypologyCompoundObject);
133
		Set<Field> textualFields = new HashSet<Field>(commonFields);
134
		textualFields.add(cObjTypologyTextual);
135
		Set<Field> dataSetFields = new HashSet<Field>(commonFields);
136
		dataSetFields.add(cObjTypologyDataSet);
137
		
138
		aggregationObjects = new Entity("AggregationObjects", compoundObjectFields, cObjIdentifier.getName(), cObjTypologyCompoundObject.getName(), title.getName(), true, "Aggregation Object", 0xffa9a9ff, "diamond");
139
		ePrints = new Entity("ePrints", textualFields, cObjIdentifier.getName(), cObjTypologyTextual.getName(), title.getName(), false, "E-Print", 0xffdd7a00, "circle");
140
		ePubs = new Entity("ePubs", compoundObjectFields, cObjIdentifier.getName(), cObjTypologyCompoundObject.getName(), title.getName(), true, "E-Pub", 0xffa13ba4, "square");
141
		nonEPrints = new Entity("nonEPrints", textualFields, cObjIdentifier.getName(), cObjTypologyTextual.getName(), title.getName(), false, "Non-E-Print", 0xff3a9db8, "circle");
142
		Entity researchData = new Entity("ResearchData", dataSetFields, cObjIdentifier.getName(), cObjTypologyDataSet.getName(), title.getName(), false, "Research Data", 0xff8aac46, "circle");
143
		Entity sequence = new Entity("Sequence", Collections.singleton(sequenceNo), null, null, sequenceNo.getName(), true, "Sequence", 0xff7f7f7f, "circle"); 
144
		
145
		entities = new HashSet<Entity>();
146
		entities.add(aggregationObjects);
147
		entities.add(ePrints);
148
		entities.add(ePubs);
149
		entities.add(nonEPrints);
150
		entities.add(researchData);
151
		entities.add(sequence);
152

    
153
		Set<String> components = new HashSet<String>();
154
		components.add(aggregationObjects.getName());
155
		components.add(ePrints.getName());
156
		components.add(nonEPrints.getName());
157
		components.add(researchData.getName());
158
		
159
		aggregates = new Relation("aggregates", Collections.singleton(aggregationObjects.getName()), components, "many_to_many", "part_part", "aggregates", 2, 0xff7f7f7f);
160
		Relation cites = new Relation("cites", Collections.singleton(ePrints.getName()), Collections.singleton(ePrints.getName()), "many_to_many", "part_part", "cites", 2, 0xff7f7f7f);
161
		composedBy = new Relation("composedBy", Collections.singleton(ePubs.getName()), components, "many_to_many", "part_part", "composed by", 2, 0xff7f7f7f);
162
		Relation generatedBy = new Relation("generatedBy", Collections.singleton(researchData.getName()), Collections.singleton(researchData.getName()), "many_to_many", "part_part", "generated by", 2, 0xff7f7f7f);
163
		hasEPrint = new Relation("hasEPrint", Collections.singleton(ePubs.getName()), Collections.singleton(ePrints.getName()), "many_to_one", "tot_part", "has e-print", 3, 0xffa13ba4);
164
		Relation order = new Relation("order", Collections.singleton(aggregates.getName()), Collections.singleton(sequence.getName()), "one_to_one", "part_tot", "order", 2, 0xff7f7f7f);
165
		Relation relatedWith = new Relation("relatedWith", Collections.singleton(ePubs.getName()), Collections.singleton(ePubs.getName()), "many_to_many", "part_part", "related with", 2, 0xff7f7f7f);
166
		
167
		
168
		relations = new HashSet<Relation>();
169
		relations.add(aggregates);
170
		relations.add(cites);
171
		relations.add(composedBy);
172
		relations.add(generatedBy);
173
		relations.add(hasEPrint);
174
		relations.add(order);
175
		relations.add(relatedWith);
176

    
177
		graph = new Graph();
178
		temporaryIds = new HashMap<String, Map<String, String>>();
179
		logger.debug("EPManagerMock initialized successfully");
180
	}
181

    
182
	public void setPublisherServiceLocator(ServiceLocator<PublisherService> publisherServiceLocator) {
183
		this.publisherServiceLocator = publisherServiceLocator;
184
	}
185
	
186
	
187
	public void setDocumentReader(DocumentReader documentReader) {
188
		this.documentReader = documentReader;
189
	}
190
	
191
	
192
	@Override
193
	public Set<Entity> getEntities() {
194
		logger.debug("Retrieved entities");
195
		return entities;
196
	}
197
	
198
	
199
	@Override
200
	public Set<Relation> getRelations() {
201
		logger.debug("Retrieved relations");
202
		return relations;
203
	}
204
	
205

    
206
	@Override
207
	public Set<Map<String, List<String>>> getDropboxContents(UserProfile userProfile) throws EPManagerException {
208
		Set<Map<String, List<String>>> dropboxContents = new HashSet<Map<String, List<String>>>();
209
		try {
210
			for (String documentId : userProfile.getDocumentIds()) {
211
				String xml = publisherServiceLocator.getService().getResourceById(documentId, FORMAT);
212
				Map<String, List<String>> document = null;
213
				if (xml != null)
214
					document = documentReader.read(xml).getMap();
215
				else
216
					document = getNode(documentId).getDocumentMap();
217
				if (document != null)
218
					dropboxContents.add(document);
219
			}
220
		} catch (PublisherServiceException e) {
221
			logger.error("Error retrieving dropbox contents of user " + userProfile, e);
222
			throw new EPManagerException("Error retrieving dropbox contents of user " + userProfile, e);
223
		}
224
		logger.debug("Retrieved dropbox contents of user " + userProfile);
225
		return dropboxContents;
226
	}
227

    
228
	@Override
229
	public Graph getGraph(String rootId) {
230
		Graph graph = new Graph();
231
		Node root = getNode(rootId);
232
		if (root == null) {
233
			logger.debug("No graph with root " + rootId + " exists");
234
			return null;
235
		}
236
		graph.getNodes().add(root);
237
		for (RelatedNode parent : getParents(root)) {
238
			Node node = parent.getNode();
239
			graph.getNodes().add(node);
240
			graph.getEdges().add(new Edge(parent.getRelation(), node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0), root.getDocumentMap().get(getEntity(root.getEntity()).getIdField()).get(0)));
241
		}
242
		getDescendants(root, graph);
243
		logger.debug("Retrieved graph with root " + rootId);
244
		return graph;
245
	}
246
	
247
	
248
	@Override
249
	public void saveGraph(UserProfile userProfile, String [] commands) throws EPManagerException {
250
		for (String command : commands)
251
			executeCommand(userProfile, command);
252
		temporaryIds.put(userProfile.getResourceId(), null);
253
		logger.debug("User " + userProfile + " saved graph");
254
	}
255
	
256
	
257
	@Override
258
	public String saveEnhancedPublication(UserProfile userProfile, String description, String language, String subject, String title, String ePrintId, Set<String> nonEPrintIds) throws EPManagerException {
259
		Map<String, List<String>> document = new HashMap<String, List<String>>();
260
		document.put(DOCUMENT_PREFIX + this.description.getName(), new ArrayList<String>());
261
		document.get(DOCUMENT_PREFIX + this.description.getName()).add(description);
262
		document.put(DOCUMENT_PREFIX + this.language.getName(), new ArrayList<String>());
263
		document.get(DOCUMENT_PREFIX + this.language.getName()).add(language);
264
		document.put(DOCUMENT_PREFIX + this.subject.getName(), new ArrayList<String>());
265
		document.get(DOCUMENT_PREFIX + this.subject.getName()).add(subject);
266
		document.put(DOCUMENT_PREFIX + this.title.getName(), new ArrayList<String>());
267
		document.get(DOCUMENT_PREFIX + this.title.getName()).add(title);
268
		String id = createNode(userProfile, TEMP_ID_PREFIX + Math.round(Math.random() * Long.MAX_VALUE), ePubs.getName());
269
		editNode(userProfile, id, document);
270
		importNode(userProfile, ePrintId, ePrints.getName());
271
		addEdge(userProfile, hasEPrint.getName(), id, ePrintId);
272
		for (String nonEPrintId : nonEPrintIds) {
273
			importNode(userProfile, nonEPrintId, nonEPrints.getName());
274
			addEdge(userProfile, composedBy.getName(), id, nonEPrintId);
275
		}
276
		logger.debug("User " + userProfile + " saved enhanced publication " + id);
277
		return id;
278
	}
279

    
280
	@Override
281
	public String saveAggregationObject(UserProfile userProfile, String description, String language, String subject, String title, Set<String> contentIds) throws EPManagerException {
282
		Map<String, List<String>> document = new HashMap<String, List<String>>();
283
		document.put(DOCUMENT_PREFIX + this.description.getName(), new ArrayList<String>());
284
		document.get(DOCUMENT_PREFIX + this.description.getName()).add(description);
285
		document.put(DOCUMENT_PREFIX + this.language.getName(), new ArrayList<String>());
286
		document.get(DOCUMENT_PREFIX + this.language.getName()).add(language);
287
		document.put(DOCUMENT_PREFIX + this.subject.getName(), new ArrayList<String>());
288
		document.get(DOCUMENT_PREFIX + this.subject.getName()).add(subject);
289
		document.put(DOCUMENT_PREFIX + this.title.getName(), new ArrayList<String>());
290
		document.get(DOCUMENT_PREFIX + this.title.getName()).add(title);		
291
		String id = createNode(userProfile, TEMP_ID_PREFIX + Math.round(Math.random() * Long.MAX_VALUE), aggregationObjects.getName());
292
		editNode(userProfile, id, document);
293
		for (String contentId : contentIds) {
294
			importNode(userProfile, contentId, nonEPrints.getName());
295
			addEdge(userProfile, aggregates.getName(), id, contentId);
296
		}
297
		logger.debug("User " + userProfile + " saved aggregation object " + id);
298
		return id;
299
	}
300
	
301
	@Override
302
	public DocumentPage getEnhancedPublications(int pageSize, int pageNumber) {
303
		List<Document> documents = new ArrayList<Document>();
304
		for (Node node : graph.getNodes()) {
305
			if (node.getEntity().equals(ePubs.getName()))
306
				documents.add(new Document(node.getDocumentMap()));
307
		} 
308
		int numberOfDocuments = documents.size();
309
		int numberOfPages = numberOfDocuments / pageSize;
310
		if ((numberOfDocuments % pageSize) > 0)
311
			numberOfPages++;
312
		int start = (pageNumber - 1) * pageSize;
313
		if (start < 0)
314
			start = 0;
315
		int end = pageNumber * pageSize;
316
		if (end > numberOfDocuments)
317
			end = numberOfDocuments;
318
		documents = documents.subList(start, end);
319
		logger.debug("Retrieved enhanced publications");
320
		return new DocumentPage(documents, pageSize, pageNumber, numberOfDocuments, numberOfPages);
321
	}
322
	
323
	
324
	@Override
325
	public Document getEnhancedPublication(String id) {
326
		Node node = getNode(id);
327
		if ((node == null) || (!node.getEntity().equals(ePubs.getName()))) {
328
			logger.debug("Enhanced publication " + id + " not found");
329
			return null;
330
		} else {
331
			logger.debug("Retrieved enhanced publication " + id);
332
			return new Document(node.getDocumentMap());
333
		}
334
	}
335
	
336

    
337
	@Override
338
	public Node getNode(String id) {
339
		for (Node node : graph.getNodes()) {
340
			if (node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0).equals(id)) {
341
				logger.debug("Retrieved node " + id);
342
				return node;
343
			}
344
		}
345
		logger.debug("Node " + id + " not found");
346
		return null;
347
	}
348

    
349
	
350
	@Override
351
	public Set<RelatedNode> getParents(Node node) {
352
		Set<RelatedNode> parents = new HashSet<RelatedNode>();
353
		String id = node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0);
354
		for (Edge edge : graph.getEdges()) {
355
			if (edge.getTarget().equals(id))
356
				parents.add(new RelatedNode(edge.getRelation(), getNode(edge.getSource())));
357
		}
358
		logger.debug("Retrieved parents of node " + id);
359
		return parents;
360
	}
361
	
362

    
363
	@Override
364
	public Set<RelatedNode> getChildren(Node node) {
365
		Set<RelatedNode> children = new HashSet<RelatedNode>();
366
		String id = node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0);
367
		for (Edge edge : graph.getEdges()) {
368
			if (edge.getSource().equals(id))
369
				children.add(new RelatedNode(edge.getRelation(), getNode(edge.getTarget())));
370
		}
371
		logger.debug("Retrieved children of node " + id);
372
		return children;
373
	}
374
	
375
		
376
	private void getDescendants(Node root, Graph graph){
377
		String rootId = root.getDocumentMap().get(getEntity(root.getEntity()).getIdField()).get(0);
378
		for (RelatedNode child : getChildren(root)) {
379
			Node node = child.getNode();
380
			graph.getNodes().add(node);
381
			graph.getEdges().add(new Edge(child.getRelation(), rootId, node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0)));
382
			getDescendants(node, graph);
383
		}
384
		logger.debug("Retrieved descendants of node " + rootId);
385
	}
386
	
387
	
388
	private void executeCommand(UserProfile userProfile, String command) throws EPManagerException {
389
		Map<String, List<String>> arguments = parseCommand(command);
390
		if (arguments.get(COMMAND).get(0).equals(CREATE)) {
391
			createNode(userProfile, arguments.get(ID).get(0), arguments.get(ENTITY).get(0));
392
		} else if (arguments.get(COMMAND).get(0).equals(IMPORT)) {
393
			importNode(userProfile, arguments.get(ID).get(0), arguments.get(ENTITY).get(0));
394
		} else if (arguments.get(COMMAND).get(0).equals(EDIT)) {
395
			editNode(userProfile, arguments.get(ID).get(0), arguments);
396
		} else if (arguments.get(COMMAND).get(0).equals(DELETE)) {
397
			deleteNode(userProfile, arguments.get(ID).get(0));
398
		} else if (arguments.get(COMMAND).get(0).equals(ADD)) {
399
			addEdge(userProfile, arguments.get(RELATION).get(0), arguments.get(SOURCE).get(0), arguments.get(TARGET).get(0));
400
		} else if (arguments.get(COMMAND).get(0).equals(REMOVE)) {
401
			removeEdge(userProfile, arguments.get(RELATION).get(0), arguments.get(SOURCE).get(0), arguments.get(TARGET).get(0));
402
		}
403
		logger.debug("User " + userProfile + " executed command " + command);
404
	}
405
	
406
	private Map<String, List<String>> parseCommand(String command) throws EPManagerException {
407
		Map<String, List<String>> arguments = new HashMap<String, List<String>>();
408
		try {
409
			for (String parameter: command.split(PARAMETER_DELIMITER)) {
410
				String [] pair = parameter.split(VALUE_DELIMITER);
411
				String key = URLDecoder.decode(pair[0], UTF8);
412
				String value = (pair.length > 1) ? URLDecoder.decode(pair[1], UTF8) : "";
413
				if (arguments.get(key) == null)
414
					arguments.put(key, new ArrayList<String>());
415
				arguments.get(key).add(value);
416
			}
417
		} catch (UnsupportedEncodingException e) {
418
			logger.error("Error parsing command " + command);
419
			throw new EPManagerException("Error parsing command " + command, e);
420
		}
421
		return arguments;
422
	}
423
	
424
	
425
	private String createNode(UserProfile userProfile, String id, String entity) {
426
		String userId = userProfile.getResourceId();
427
		String uuid = UUID.randomUUID().toString();
428
		if (temporaryIds.get(userId) == null)
429
			temporaryIds.put(userId, new HashMap<String, String>());
430
		temporaryIds.get(userId).put(id, uuid);
431
		Entity ent = getEntity(entity);
432
		Map<String, List<String>> document = new HashMap<String, List<String>>();
433
		
434
		for (Field field : ent.getFields()) {
435
			String name = field.getName();
436
			String defaultValue = field.getDefaultValue();
437
			document.put(name, new ArrayList<String>());
438
			if (name.equals(ent.getIdField()))
439
				document.get(name).add(uuid);
440
			if (defaultValue == null)
441
				continue;
442
			else if(defaultValue.equals(USER_PLACEHOLDER)) {
443
				String user = userProfile.getFirstname() + " " + userProfile.getLastname();
444
				if (user.trim().isEmpty())
445
					user = userProfile.getEmail();
446
				document.get(name).add(user);
447
			} else
448
				document.get(name).add(defaultValue);
449
		}
450
		graph.getNodes().add(new Node(entity, document));
451
		logger.debug("User " + userProfile + " created node " + id + " as " + entity + " (new id " + uuid + ")");
452
		return uuid;
453
	}
454
	
455
	private void importNode(UserProfile userProfile, String id, String entity) throws EPManagerException {
456
		Entity ent = getEntity(entity);
457
		for (Map<String, List<String>> document: getDropboxContents(userProfile)) {
458
			if (document.get(ent.getIdField()).get(0).equals(id)) {
459
				graph.getNodes().add(new Node(entity, document));
460
				logger.debug("User " + userProfile + " imported node " + id + " as " + entity);
461
				return;
462
			}
463
		}
464
		logger.debug("Document " + id + " not found in dropbox of user " + userProfile);
465
	}
466
	
467
	private void editNode(UserProfile userProfile, String id, Map<String, List<String>> document) {
468
		id = resolveId(userProfile.getResourceId(), id);
469
		for (Node node : graph.getNodes()) {
470
			Entity entity = getEntity(node.getEntity());
471
			if (node.getDocumentMap().get(entity.getIdField()).get(0).equals(id)) {
472
				for (Field field : entity.getFields()) {
473
					String name = field.getName();
474
					List<String> values = document.get(DOCUMENT_PREFIX + name);
475
					if (values != null)
476
							node.getDocumentMap().put(name, values);
477
				}
478
				logger.debug("User " + userProfile + " edited node " + id);
479
				return;
480
			}
481
		}
482
	}
483
	
484
	private void deleteNode(UserProfile userProfile, String id) {
485
		id = resolveId(userProfile.getResourceId(), id);
486
		for (Iterator<Node> i = graph.getNodes().iterator(); i.hasNext();) {
487
			Node node = i.next();
488
			if (node.getDocumentMap().get(getEntity(node.getEntity()).getIdField()).get(0).equals(id)) {
489
				for (RelatedNode parent : getParents(node)) // break relations with parents
490
					removeEdge(userProfile, parent.getRelation(), parent.getNode().getDocumentMap().get(getEntity(parent.getNode().getEntity()).getIdField()).get(0), id);
491
				for (RelatedNode child: getChildren(node)) // break relations with children
492
					removeEdge(userProfile, child.getRelation(), id, child.getNode().getDocumentMap().get(getEntity(child.getNode().getEntity()).getIdField()).get(0));
493
				i.remove(); // remove node
494
				break;
495
			}
496
		}		
497
		logger.debug("User " + userProfile + " deleted node " + id);
498
	}
499
	
500
	private void addEdge(UserProfile userProfile, String relation, String source, String target) {
501
		source = resolveId(userProfile.getResourceId(), source);
502
		target = resolveId(userProfile.getResourceId(), target);
503
		graph.getEdges().add(new Edge(relation, source, target));
504
		logger.debug("User " + userProfile + " added edge " + relation + " from node " + source + " to node " + target);
505
	}
506
	
507
	private void removeEdge(UserProfile userProfile, String relation, String source, String target) {
508
		source = resolveId(userProfile.getResourceId(), source);
509
		target = resolveId(userProfile.getResourceId(), target);
510
		for (Iterator<Edge> i = graph.getEdges().iterator(); i.hasNext();) {
511
			Edge edge = i.next();
512
			if (edge.getRelation().equals(relation) && edge.getSource().equals(source) && edge.getTarget().equals(target)) {
513
				i.remove();
514
				break;
515
			}
516
		}
517
		logger.debug("User " + userProfile + " removed edge " + relation + " from node " + source + " to node " + target);
518
	}
519
	
520
	private Entity getEntity(String name) {
521
		for (Entity entity : entities) {
522
			if (entity.getName().equals(name))
523
				return entity;
524
		}
525
		return null;
526
	}
527
	
528
	private String resolveId(String userId, String id) {
529
		return id.startsWith(TEMP_ID_PREFIX) ? temporaryIds.get(userId).get(id) : id;
530
	}
531
}
(5-5/13)