
com.ardoq.util.SyncUtil Maven / Gradle / Ivy
package com.ardoq.util;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import com.ardoq.ArdoqClient;
import com.ardoq.model.AggregatedWorkspace;
import com.ardoq.model.BasicModel;
import com.ardoq.model.Component;
import com.ardoq.model.Model;
import com.ardoq.model.Reference;
import com.ardoq.model.Tag;
import com.ardoq.model.Workspace;
import com.ardoq.service.AttachmentService;
import com.ardoq.service.ComponentService;
import com.ardoq.service.ReferenceService;
import com.ardoq.service.TagService;
import com.ardoq.service.WorkspaceService;
import com.google.gson.Gson;
import retrofit.RestAdapter;
/**
* Created by magnulf on 23.04.14.
*/
public class SyncUtil {
public static final String SPLIT_CHARACTER = "\u0000"; //NULL
private final ArdoqClient client;
private final WorkspaceService workspaceService;
private Workspace workspace;
private final ComponentService componentService;
private final ReferenceService referenceService;
private final TagService tagService;
private final Model model;
private final AttachmentService attachmentService;
private AggregatedWorkspace aggregatedWorkspace;
Gson gson = new Gson();
private HashMap newComponents = new HashMap();
private HashMap currentComponents = new HashMap();
private HashMap componentTree = new HashMap();
private HashMap tags = new HashMap();
private HashMap currentReferences = new HashMap();
private AbstractMap referenceMap = new HashMap();
;
private HashMap newRefs = new HashMap();
private Collection modifiedList = new LinkedList();
private Collection updatedTags = new LinkedList();
private int updatedRefCount = 0;
private int updatedComponentCount = 0;
private int deletedComponents = 0;
private int deletedRefs = 0;
public SyncUtil(ArdoqClient client, Workspace workspace) {
this.client = client;
this.workspaceService = client.workspace();
this.componentService = client.component();
this.referenceService = client.reference();
this.attachmentService = client.attachment();
this.tagService = client.tag();
this.model = client.model().getModelById(workspace.getComponentModel());
this.workspace = workspace;
loadCurrentAggregatedWorkspace();
}
private void loadCurrentAggregatedWorkspace() {
this.aggregatedWorkspace = this.workspaceService.getAggregatedWorkspace(workspace.getId());
this.createComponentTree();
this.createReferenceMap();
this.createTagMap();
}
private void createTagMap() {
for (Tag tag : this.aggregatedWorkspace.getTags()) {
this.tags.put(tag.getName(), tag);
}
}
private void createReferenceMap() {
for (Reference ref : this.aggregatedWorkspace.getReferences()) {
this.currentReferences.put(this.getRefKey(ref), ref);
this.referenceMap.put(ref.getId(), ref);
}
}
private void updateCachedRefs(Reference ref) {
this.currentReferences.put(this.getRefKey(ref), ref);
this.referenceMap.put(ref.getId(), ref);
}
private void updateCachedComponents(Component c) {
if (c.getId() != null) {
this.currentComponents.put(c.getId(), c);
this.componentTree.put(this.getPath(c), c);
} else {
throw new RuntimeException("Component " + c.getName() + " has no id, cannot cache it:\n" + c);
}
}
private void createComponentTree() {
for (Component c : this.aggregatedWorkspace.getComponents()) {
this.currentComponents.put(c.getId(), c);
if (c.getParent() == null) {
this.componentTree.put(c.getName(), c);
}
}
for (Component c : this.aggregatedWorkspace.getComponents()) {
if (c.getParent() != null) {
this.componentTree.put(this.getPath(c), c);
}
}
}
private String getPath(Component c) {
String name = c.getName();
Component parent = this.currentComponents.get(c.getParent());
while (parent != null) {
name = parent.getName() + SPLIT_CHARACTER + name;
parent = this.currentComponents.get(parent.getParent());
}
return name;
}
/**
* Gets an existing tag by name
*
* @param name Name of the tag
* @return Returns the tag
*/
public Tag getTagByName(String name) {
Tag t = this.tags.get(name);
if (null == t) {
t = new Tag(name, this.workspace.getId(), "");
this.tags.put(name, t);
}
return t;
}
public void updateTag(Tag tag) {
this.tags.put(tag.getName(), tag);
boolean found = false;
for (Tag t : this.updatedTags) {
if (t.getName().equals(tag.getName())) {
found = true;
}
}
if (!found) {
this.updatedTags.add(tag);
}
}
public void syncTags() {
for (Tag t : this.updatedTags) {
if (null == t.getId()) {
Tag nt = tagService.createTag(t);
this.tags.put(nt.getName(), nt);
} else {
tagService.updateTag(t.getId(), t);
this.tags.put(t.getName(), t);
}
}
}
public Component getComponentByPath(String compPath) {
return (Component) this.clone(this.componentTree.get(compPath));
}
public Component getComponentByPath(Component comp) {
return (Component) this.clone(this.componentTree.get(this.getPath(comp)));
}
public BasicModel clone(BasicModel obj) {
return (null != obj) ? gson.fromJson(gson.toJson(obj), obj.getClass()) : null;
}
public Component getComponentById(String id) {
return this.currentComponents.get(id);
}
public Component addComponent(Component comp) {
Component currentComp = this.getComponentByPath(comp);
if (null == currentComp) {
currentComp = this.componentService.createComponent(comp);
this.newComponents.put(currentComp.getId(), currentComp);
this.componentTree.put(getPath(currentComp), currentComp);
} else if (this.isDifferent(currentComp, comp)) {
this.updatedComponentCount++;
comp.setCreated(null);
currentComp = componentService.updateComponent(currentComp.getId(), comp);
}
this.modifiedList.add(currentComp);
this.updateCachedComponents(currentComp);
return currentComp;
}
private String getRefKey(Reference ref) {
return ref.getSource() + ref.getType() + ref.getTarget();
}
public Reference getCurrentReference(Reference ref) {
return this.currentReferences.get(this.getRefKey(ref));
}
public Reference getCurrentReferenceById(String id) {
return this.referenceMap.get(id);
}
public Reference addReference(Reference ref) {
Reference currentRef = getCurrentReference(ref);
if (null == currentRef) {
currentRef = referenceService.createReference(ref);
this.newRefs.put(this.getRefKey(currentRef), currentRef);
} else if (this.isDifferent(currentRef, ref)) {
ref.setCreated(null);
currentRef = referenceService.updateReference(currentRef.getId(), ref);
this.updatedRefCount++;
}
this.modifiedList.add(currentRef);
this.updateCachedRefs(ref);
return currentRef;
}
/**
* Returns an update report with statistics of created, updated and deleted references and components.
*
* @return a String with the report.
*/
public String getReport() {
return "Report\n - Created " + newComponents.size() + " components\n - Updated " + this.updatedComponentCount + " components\n - Created " + newRefs.size() + " references\n - Updated " + this.updatedRefCount + " references\n - Deleted " + this.deletedComponents + " components\n - Deleted " + this.deletedRefs + " references";
}
public void deleteNotSyncedItems() {
this.deleteOldReferences(this.deleteOldComponents());
}
public Set deleteOldReferences(Set deletedComponents) {
Set refsToDelete = getObjectsToDelete(this.referenceMap.keySet());
for (String id : refsToDelete) {
Reference ref = this.referenceMap.get(id);
if (id != null && id.trim().length() > 0 && ref != null && !deletedComponents.contains(ref.getSource()) && !deletedComponents.contains(ref.getTarget())) {
try {
this.referenceService.deleteReference(id);
} catch (Exception ite) {
System.out.println("Reference with id: " + id + " was already deleted.");
}
this.deletedRefs++;
}
}
return refsToDelete;
}
public Set deleteOldComponents() {
Set componentsToDelete = getObjectsToDelete(this.currentComponents.keySet());
for (String id : componentsToDelete) {
deletedComponents++;
try {
this.componentService.deleteComponent(id);
} catch (Exception ite) {
System.out.println("Component with id: " + id + " was already deleted.");
}
}
return componentsToDelete;
}
private Set getObjectsToDelete(Set objectIdsToDelete) {
Set componentsToDelete = objectIdsToDelete;
for (BasicModel model : this.modifiedList) {
componentsToDelete.remove(model.getId());
}
return componentsToDelete;
}
public Workspace updateWorkspaceIfDifferent(Workspace newWorkspace) {
Workspace existingWorkspace = this.workspaceService.getWorkspaceById(this.workspace.getId());
if (this.isDifferent(existingWorkspace, newWorkspace)) {
this.workspace = this.workspaceService.updateWorkspace(this.workspace.getId(), newWorkspace);
}
return this.workspace;
}
public Workspace getWorkspace() {
return this.workspace;
}
public Model getModel() {
return this.model;
}
public AggregatedWorkspace getAggregatedWorkspace() {
return this.aggregatedWorkspace;
}
private boolean isDifferent(BasicModel current, BasicModel newComp) {
boolean isDifferent = false;
for (java.lang.reflect.Field f : newComp.getClass().getDeclaredFields()) {
try {
f.setAccessible(true);
Object newValue = f.get(newComp);
Object oldValue = f.get(current);
if (newValue != null) {
if (newValue.getClass().getSimpleName().indexOf("Map") > -1) {
Map newVal = (Map) newValue;
Map oldVal = (Map) oldValue;
boolean mapDifferent = addIfFoundAndCheckDifferent(newVal, oldVal);
isDifferent = isDifferent || mapDifferent;
} else if (!newValue.equals(oldValue)) {
isDifferent = true;
}
} else if (oldValue != null) {
f.set(newComp, oldValue);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return isDifferent;
}
private boolean addIfFoundAndCheckDifferent(Map newMap, Map oldMap) {
boolean isDifferent = false;
for (Object key : oldMap.keySet()) {
Object val = newMap.get(key);
Object oldVal = oldMap.get(key);
//TODO: Check arrayt list v.s. gson array
if (val != null && oldVal != null && !oldVal.equals(val)) {
isDifferent = true;
} else if (null != oldVal && !newMap.containsKey(key)) {
newMap.put(key, oldVal);
}
}
for (Object key : newMap.keySet()) {
Object val = newMap.get(key);
Object oldVal = oldMap.get(key);
if ((val != null && !val.equals(oldVal)) || (oldVal != null && !oldVal.equals(val))) {
isDifferent = true;
}
}
return isDifferent;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy