package org.minimalj.backend;

import java.io.File;
import java.util.List;

import org.minimalj.application.Application;
import org.minimalj.backend.sql.SqlPersistence;
import org.minimalj.transaction.criteria.Criteria;
import org.minimalj.util.StringUtils;

/**
 * The common interface of all types of persistences. Note that specific implementations
 * can have more methods. See for example the <code>execute</code> methods in SqlPersistence
 *
 */
public abstract class Persistence {

	private static Persistence instance;
	
	private static Persistence createPersistence() {
		String database = System.getProperty("MjBackendDatabase");
		String user = System.getProperty("MjBackendDatabaseUser", "APP");
		String password = System.getProperty("MjBackendDatabasePassword", "APP");
		Class<?>[] entityClasses = Application.getApplication().getEntityClasses();
		if (StringUtils.isBlank(database)) {
			String databaseFile = System.getProperty("MjBackendDatabaseFile", null);
			boolean createTables = databaseFile == null || !new File(databaseFile).exists();
			return new SqlPersistence(SqlPersistence.embeddedDataSource(databaseFile), createTables, entityClasses);
		} else {
			return new SqlPersistence(SqlPersistence.mariaDbDataSource(database, user, password), entityClasses);
		}
	}

	public static Persistence getInstance() {
		if (instance == null) {
			instance = createPersistence();
		}
		return instance;
	}
	
	// transaction

	public abstract void startTransaction(int transactionIsolationLevel);
	
	public abstract void endTransaction(boolean commit);
	
	
	// object handling
	
	public abstract <T> T read(Class<T> clazz, Object id);

	public abstract <T> List<T> read(Class<T> clazz, Criteria criteria, int maxResults);

	public abstract <T> Object insert(T object);

	public abstract <T> void update(T object);

	public abstract <T> void delete(Class<T> clazz, Object id);
	
	// list handling, list name is the name of the property containing the list
	
	public abstract <ELEMENT> List<ELEMENT> getList(String listName, Object parentId);

	public abstract <ELEMENT> ELEMENT add(String listName, Object parentId, ELEMENT element);

	public abstract void remove(String listName, Object parentId, int position);

}

@@ -67,16 +67,49 @@
 il.List;
+%0Aimport java.util.logging.Logger;
 %0A%0Aimport
@@ -246,16 +246,66 @@
 iteria;%0A
+import org.minimalj.util.LoggingRuntimeException;%0A
 import o
@@ -563,16 +563,101 @@
 stence %7B
+%0A%09private static final Logger logger = Logger.getLogger(Persistence.class.getName());
 %0A%0A%09priva
@@ -749,23 +749,35 @@
 %09String 
-databas
+persistenceClassNam
 e = Syst
@@ -786,39 +786,506 @@
 .getProperty(%22Mj
-Backend
+Persistence%22);%0A%09%09if (!StringUtils.isBlank(persistenceClassName)) %7B%0A%09%09%09try %7B%0A%09%09%09%09@SuppressWarnings(%22unchecked%22)%0A%09%09%09%09Class%3C? extends Persistence%3E persistenceClass = (Class%3C? extends Persistence%3E) Class.forName(persistenceClassName);%0A%09%09%09%09Persistence persistence = persistenceClass.newInstance();%0A%09%09%09%09return persistence;%0A%09%09%09%7D catch (Exception x) %7B%0A%09%09%09%09throw new LoggingRuntimeException(x, logger, %22Set backend failed%22);%0A%09%09%09%7D%0A%09%09%7D %0A%09%09%0A%09%09String database = System.getProperty(%22MjSql
 Database%22);%0A%09%09St
@@ -1310,39 +1310,35 @@
 .getProperty(%22Mj
-Backend
+Sql
 DatabaseUser%22, %22
@@ -1378,39 +1378,35 @@
 .getProperty(%22Mj
-Backend
+Sql
 DatabasePassword
@@ -1584,15 +1584,11 @@
 (%22Mj
-Backend
+Sql
 Data

make it configurable by system properties