package org.basex.core.cmd;
import static org.basex.core.Text.*;
import static org.basex.util.Token.*;
import org.basex.core.Prop;
import org.basex.core.User;
import org.basex.data.Data;
import org.basex.data.MetaData;
import org.basex.io.IOFile;
import org.basex.util.list.IntList;
/**
* Evaluates the 'rename' command and renames resources or directories
* in a collection.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class Rename extends ACreate {
/**
* Default constructor.
* @param source source path
* @param target target path
*/
public Rename(final String source, final String target) {
super(DATAREF | User.WRITE, source, target);
}
@Override
protected boolean run() {
final Data data = context.data();
final String src = MetaData.normPath(args[0]);
if(src == null) return error(NAME_INVALID_X, args[0]);
final String trg = MetaData.normPath(args[1]);
if(trg == null) return error(NAME_INVALID_X, args[1]);
boolean ok = true;
int c = 0;
final IntList docs = data.resources.docs(src);
for(int i = 0, ds = docs.size(); i < ds; i++) {
final int pre = docs.get(i);
final String target = target(data, pre, src, trg);
if(target.isEmpty()) {
info(NAME_INVALID_X, target);
ok = false;
} else {
data.update(pre, Data.DOC, token(target));
c++;
}
}
// data was changed: update context
if(c != 0) data.flush();
if(!ok) return false;
final IOFile file = data.meta.binary(src);
if(file != null && file.exists()) {
final IOFile target = data.meta.binary(trg);
final IOFile trgdir = new IOFile(target.dir());
if(!trgdir.exists() && !trgdir.md() || !file.rename(target)) {
return error(NAME_INVALID_X, trg);
}
c++;
}
return info(DOCS_RENAMED_X_X, c, perf);
}
/**
* Generates a target path for the specified document.
* @param data data reference
* @param pre pre value of the document
* @param src source path
* @param trg target path
* @return new name
*/
public static String target(final Data data, final int pre, final String src,
final String trg) {
// source references a file
final String path = string(data.text(pre, true));
if(Prop.WIN ? path.equalsIgnoreCase(src) : path.equals(src)) return trg;
// source references a directory: merge target path and file name
final String name = path.substring(src.length() + 1);
return !trg.isEmpty() ? trg + '/' + name : name;
}
}