/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.server.etl;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.exception.OSchemaException;
import com.orientechnologies.orient.core.intent.OIntentMassiveInsert;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.OCommandSQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Decebal Suiu
*/
public class OrientDbLoader implements Loader {
private static final Logger log = LoggerFactory.getLogger(OrientDbLoader.class);
private String dbUrl;
private String dbUser = "admin";
private String dbPassword = "admin";
private boolean dbAutoCreate = true;
private boolean dbAutoDropIfExists;
private boolean dbAutoCreateProperties;
private int batchCommit;
private long batchCounter;
private ODatabaseDocumentTx documentDatabase;
private String className;
private boolean autoDropClass;
public String getDbUrl() {
return dbUrl;
}
public void setDbUrl(String dbUrl) {
this.dbUrl = dbUrl;
}
public String getDbUser() {
return dbUser;
}
public void setDbUser(String dbUser) {
this.dbUser = dbUser;
}
public String getDbPassword() {
return dbPassword;
}
public void setDbPassword(String dbPassword) {
this.dbPassword = dbPassword;
}
public boolean isDbAutoCreate() {
return dbAutoCreate;
}
public void setDbAutoCreate(boolean dbAutoCreate) {
this.dbAutoCreate = dbAutoCreate;
}
public boolean isDbAutoDropIfExists() {
return dbAutoDropIfExists;
}
public void setDbAutoDropIfExists(boolean dbAutoDropIfExists) {
this.dbAutoDropIfExists = dbAutoDropIfExists;
}
public boolean isDbAutoCreateProperties() {
return dbAutoCreateProperties;
}
public void setDbAutoCreateProperties(boolean dbAutoCreateProperties) {
this.dbAutoCreateProperties = dbAutoCreateProperties;
}
public int getBatchCommit() {
return batchCommit;
}
public void setBatchCommit(int batchCommit) {
this.batchCommit = batchCommit;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
if (className.contains(" ")) {
log.debug("Class name '{}' contains space characters. Replace space characters with '_'", className);
this.className = className.replace(' ', '_');
} else {
this.className = className;
}
}
public boolean isAutoDropClass() {
return autoDropClass;
}
public void setAutoDropClass(boolean autoDropClass) {
this.autoDropClass = autoDropClass;
}
@Override
public void init() {
log.debug("Init loader");
documentDatabase = new ODatabaseDocumentTx(dbUrl, false);
String databaseName = documentDatabase.getName();
if (documentDatabase.exists() && dbAutoDropIfExists) {
log.debug("Dropping existent database '{}'", databaseName);
documentDatabase.open(dbUser, dbPassword).drop();
}
if (documentDatabase.exists()) {
log.debug("Open database '{}'", databaseName);
documentDatabase.open(dbUser, dbPassword);
if ((className != null) && autoDropClass) {
OSchema schema = documentDatabase.getMetadata().getSchema();
if (schema.existsClass(className)) {
log.debug("Dropping class '{}'", className);
documentDatabase.command(new OCommandSQL("DELETE FROM " + className)).execute();
schema.dropClass(className);
}
}
} else {
long time = System.currentTimeMillis();
log.debug("Create database '{}'", databaseName);
documentDatabase.create();
time = System.currentTimeMillis() - time;
log.debug("Created database '{}' in {} ms", databaseName, time);
}
documentDatabase.declareIntent(new OIntentMassiveInsert());
}
@Override
public void load(Row row) {
if (row == null) {
return;
}
ODocument document = (ODocument) row.getPayload();
if (dbAutoCreateProperties) {
createProperties(row);
}
if (className != null) {
document.setClassName(className);
}
if (!documentDatabase.getTransaction().isActive()) {
// begin the transaction first
documentDatabase.begin();
}
// log.debug("Load document {}", document);
document.save();
if (batchCommit > 0) {
if (batchCounter > batchCommit) {
documentDatabase.commit();
documentDatabase.begin();
batchCounter = 0;
} else
batchCounter++;
}
}
@Override
public void destroy() {
log.debug("Destroy loader");
documentDatabase.close();
}
protected OClass getOrCreateClass(String className) {
OClass clazz;
OSchema schema = documentDatabase.getMetadata().getSchema();
if (schema.existsClass(className)) {
clazz = schema.getClass(className);
} else {
clazz = schema.createClass(className);
log.debug("Created class '{}'", className);
}
return clazz;
}
protected void createProperties(Row row) {
OClass clazz;
if (className != null) {
clazz = getOrCreateClass(className);
} else {
clazz = ((ODocument) row.getPayload()).getSchemaClass();
}
int count = row.getFieldCount();
for (int i = 0; i < count; i++) {
String fieldName = row.getFieldName(i);
OProperty property = clazz.getProperty(fieldName);
if (property == null) {
OType type = OType.getTypeByClass(row.getFieldType(i));
try {
clazz.createProperty(fieldName, type);
} catch (OSchemaException e) {
log.error(e.getMessage(), e);
}
log.debug("Created property '{}' of type '{}'", fieldName, type);
}
}
}
}