/*******************************************************************************
* Copyright (c) 2013, 2015 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Eidsness - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.tag;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.tag.ITag;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.core.runtime.CoreException;
/**
* An implementation utility for synchronizing the tags between source and destination nodes.
*/
public class PDOMTagSynchronizer implements IBTreeVisitor {
private final Database db;
private final Long searchRecord;
private final Map<String, ITag> newTags;
private final List<Long> toRemove = new ArrayList<>();
private final List<Long> toInsert = new ArrayList<>();
public PDOMTagSynchronizer(Database db, Long searchRecord, Map<String, ITag> newTags) {
this.db = db;
this.searchRecord = searchRecord;
this.newTags = newTags;
}
/**
* Complete the synchronization by deleting and inserting all required records. Return true if successful
* and false otherwise.
*/
public boolean synchronize(BTree tree) {
for (Long rm : toRemove) {
try {
long record = rm.longValue();
tree.delete(record);
db.free(record);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
toRemove.clear();
for (Long insert : toInsert) {
try {
tree.insert(insert.longValue());
} catch (CoreException e) {
CCorePlugin.log(e);
try {
db.free(insert.longValue());
} catch (CoreException e1) {
CCorePlugin.log(e1);
}
}
}
toInsert.clear();
return true;
}
@Override
public int compare(long test_record) throws CoreException {
// TODO this is the same as BTreeIterable.Descriptor.compare
long test_node = new PDOMTag(db, test_record).getNode();
// -1 if record < key, 0 if record == key, 1 if record > key
return Long.valueOf(test_node).compareTo(searchRecord);
}
@Override
public boolean visit(long existing_record) throws CoreException {
PDOMTag existingTag = new PDOMTag(db, existing_record);
String taggerId = existingTag.getTaggerId();
ITag newTag = newTags.remove(taggerId);
if (newTag == null) {
toRemove.add(Long.valueOf(existing_record));
} else if (newTag.getDataLen() > existingTag.getDataLen()) {
toRemove.add(Long.valueOf(existing_record));
PDOMTag pdomTag = existingTag.cloneWith(newTag.getBytes(0, -1));
if (pdomTag != null)
toInsert.add(Long.valueOf(pdomTag.getRecord()));
} else if (!existingTag.putBytes(0, newTag.getBytes(0, -1), -1))
CCorePlugin.log("Unable to modify data of tag record " + existing_record //$NON-NLS-1$
+ " from taggerId " + taggerId); //$NON-NLS-1$
// Try to visit the full tree.
return true;
}
}