package org.basex.core.cmd;
import static org.basex.core.Text.DB_PINNED_X;
import static org.basex.core.Text.FILE_NOT_FOUND_X;
import static org.basex.core.Text.PERM_NEEDED_X;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.transform.sax.SAXSource;
import org.basex.build.Builder;
import org.basex.build.DirParser;
import org.basex.build.DiskBuilder;
import org.basex.build.MemBuilder;
import org.basex.build.Parser;
import org.basex.build.xml.SAXWrapper;
import org.basex.core.BaseXException;
import org.basex.core.CommandBuilder;
import org.basex.core.Commands.Cmd;
import org.basex.core.Commands.CmdCreate;
import org.basex.core.Commands.CmdPerm;
import org.basex.core.Context;
import org.basex.core.Prop;
import org.basex.core.User;
import org.basex.data.Data;
import org.basex.data.MemData;
import org.basex.index.IndexToken.IndexType;
import org.basex.index.ft.FTBuilder;
import org.basex.index.value.ValueBuilder;
import org.basex.io.IO;
import org.basex.io.IOContent;
import org.basex.io.in.BufferInput;
import org.basex.io.in.LookupInput;
import org.basex.util.Util;
import org.xml.sax.InputSource;
/**
* Evaluates the 'create db' command and creates a new database.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class CreateDB extends ACreate {
/**
* Default constructor.
* @param name name of database
*/
public CreateDB(final String name) {
this(name, null);
}
/**
* Constructor, specifying an initial database input.
* @param name name of database
* @param input input reference (local/remote file or XML string)
*/
public CreateDB(final String name, final String input) {
super(name, input);
}
@Override
protected boolean run() {
final String name = args[0];
IO io = null;
Parser parser = Parser.emptyParser();
final String format = prop.get(Prop.PARSER);
if(args.length < 1 || args[1] == null) {
if(in != null && in.getByteStream() != null) {
try {
io = cache();
if(io == null) {
InputStream is = in.getByteStream();
if(!(is instanceof BufferedInputStream ||
is instanceof BufferInput)) is = new BufferedInputStream(is);
final LookupInput li = new LookupInput(is);
if(li.lookup() != -1) {
parser = new SAXWrapper(new SAXSource(new InputSource(li)),
name + '.' + format, "", context.prop);
}
}
} catch(final IOException ex) {
Util.debug(ex);
return error(Util.message(ex));
}
}
} else {
io = IO.get(args[1]);
}
if(io != null) {
if(!io.exists()) return error(FILE_NOT_FOUND_X, io);
if(io instanceof IOContent) io.name(name + '.' + format);
parser = new DirParser(io, prop, mprop.dbpath(name));
}
return build(parser, name);
}
/**
* Returns a database instance from the specified parser.
* @param name name of the database
* @param parser input parser
* @param ctx database context
* @return new database instance
* @throws IOException I/O exception
*/
public static synchronized Data create(final String name, final Parser parser,
final Context ctx) throws IOException {
// check permissions
if(!ctx.user.perm(User.CREATE))
throw new BaseXException(PERM_NEEDED_X, CmdPerm.CREATE);
// create main memory database instance
final Prop prop = ctx.prop;
if(prop.is(Prop.MAINMEM)) return MemBuilder.build(name, parser, ctx.prop);
// database is currently locked by another process
if(ctx.pinned(name)) throw new BaseXException(DB_PINNED_X, name);
// create disk builder, set database path
final Builder builder = new DiskBuilder(name, parser, ctx);
// build database and index structures
try {
final Data data = builder.build();
if(data.meta.createtext) data.setIndex(IndexType.TEXT,
new ValueBuilder(data, true).build());
if(data.meta.createattr) data.setIndex(IndexType.ATTRIBUTE,
new ValueBuilder(data, false).build());
if(data.meta.createftxt) data.setIndex(IndexType.FULLTEXT,
FTBuilder.get(data).build());
data.meta.pathindex = data.meta.createpath;
data.close();
} finally {
try { builder.close(); } catch(final IOException exx) { Util.debug(exx); }
}
return Open.open(name, ctx);
}
/**
* Returns a main memory database instance from the specified parser.
* @param parser input parser
* @param ctx database context
* @return new database instance
* @throws IOException I/O exception
*/
public static synchronized MemData mainMem(final Parser parser,
final Context ctx) throws IOException {
if(ctx.user.perm(User.CREATE)) return MemBuilder.build(parser, ctx.prop);
throw new BaseXException(PERM_NEEDED_X, CmdPerm.CREATE);
}
/**
* Returns a main memory database instance for the specified input reference.
* @param source document source
* @param ctx database context
* @return new database instance
* @throws IOException I/O exception
*/
public static synchronized MemData mainMem(final IO source, final Context ctx)
throws IOException {
if(!source.exists()) throw new FileNotFoundException(
Util.info(FILE_NOT_FOUND_X, source));
return mainMem(new DirParser(source, ctx.prop, null), ctx);
}
@Override
public void build(final CommandBuilder cb) {
cb.init(Cmd.CREATE + " " + CmdCreate.DB).args();
}
}