-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d6369bf
commit 94e6eba
Showing
4 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
plugins { | ||
id 'java-library' | ||
} | ||
|
||
java { | ||
sourceCompatibility = JavaVersion.VERSION_16 | ||
targetCompatibility = JavaVersion.VERSION_16 | ||
} | ||
|
||
dependencies { | ||
implementation 'androidx.annotation:annotation:1.3.0' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
package db.clorabase.clorem; | ||
|
||
import androidx.annotation.NonNull; | ||
|
||
import java.io.File; | ||
import java.lang.management.ThreadInfo; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.Callable; | ||
import java.util.function.Consumer; | ||
import java.util.function.Predicate; | ||
|
||
import javax.naming.NoPermissionException; | ||
|
||
/** | ||
* Clorem is a simple, easy to use, and fast database engine for java applications. | ||
* It is a no-sql database which can save POJO's directly. You can organise your data | ||
* in volumes. Each volume is like a SQL table which contains the objects as rows. You can create | ||
* as many volumes as you want. You can also create as many objects as you want in | ||
* each volume. The only limitation is that the objects implement the {@link CloremObject} | ||
* | ||
* All the methods are thread safe. You can use the database in a multi-threaded environment. | ||
* | ||
* @author author Rahil khan | ||
* @version 1.0 | ||
* @since 1.0 | ||
*/ | ||
public class Clorem { | ||
private static Clorem INSTANCE; | ||
private static File databaseDir; | ||
|
||
/** | ||
* This method returns the singleton instance of the Clorem database. | ||
* @param databaseDir The directory where the database will be stored on the disk. This directory must be writable. | ||
* @return The singleton instance of the Clorem database | ||
*/ | ||
public static Clorem getInstance(File databaseDir) { | ||
if (INSTANCE == null){ | ||
INSTANCE = new Clorem(); | ||
if (databaseDir.canRead() && databaseDir.canWrite()) | ||
Clorem.databaseDir = databaseDir; | ||
else | ||
throw new RuntimeException(new NoPermissionException("You do not have permission to read/write on this directory")); | ||
} | ||
return INSTANCE; | ||
} | ||
|
||
/** | ||
* This method creates a new volume in the database. | ||
* @param name The name of the volume | ||
*/ | ||
public void createVolume(@NonNull String name){ | ||
new File(databaseDir,name).mkdir(); | ||
} | ||
|
||
/** | ||
* This method deletes a volume from the database. All the objects in the volume will be deleted. | ||
* @param name The name of the volume | ||
*/ | ||
public void deleteVolume(@NonNull String name){ | ||
var volume = new File(databaseDir,name); | ||
var files = volume.listFiles(); | ||
for (File file : files) { | ||
file.delete(); | ||
} | ||
volume.delete(); | ||
} | ||
|
||
/** | ||
* Put an object in the database. The object must implement the {@link CloremObject} interface. | ||
* @param object The object to be saved | ||
* @param <T> The type of the object | ||
*/ | ||
public synchronized <T extends CloremObject> void put(@NonNull T object){ | ||
var volume = new File(databaseDir,object.getVolume()); | ||
if (!volume.exists() && !volume.mkdir()) | ||
throw new RuntimeException("The volume could not be created. You might not have permission to create a directory"); | ||
else | ||
CloremUtils.writeObject(object,new File(volume,object.getKey())); | ||
} | ||
|
||
/** | ||
* Get an object from the database. | ||
* @param key The key of the object | ||
* @param volume The volume in which the object is stored | ||
* @return The object | ||
*/ | ||
public synchronized Object get(@NonNull String key,@NonNull String volume){ | ||
var volumeDir = new File(databaseDir,volume); | ||
var obj = new File(volumeDir,key); | ||
if (volumeDir.isDirectory() && obj.exists()) | ||
return CloremUtils.readObject(obj); | ||
else | ||
throw new IllegalArgumentException("The volume or the object does not exist"); | ||
} | ||
|
||
/** | ||
* Update an object in the database. Only use this method when you want to update whole object. | ||
* If you want to update only a few fields of the object, use the {@link #update(String, String, Class, Consumer)} method. | ||
* The object id must be the same as the object id of the object in the database. | ||
* @param object The object to be updated | ||
* @param <T> The type of the object | ||
*/ | ||
public synchronized <T extends CloremObject> void update(@NonNull T object){ | ||
var volume = new File(databaseDir,object.getVolume()); | ||
var file = new File(volume,object.getKey()); | ||
if (volume.isDirectory() && file.exists()){ | ||
CloremUtils.writeObject(object,file); | ||
} else | ||
throw new IllegalArgumentException("The volume or the object does not exist"); | ||
} | ||
|
||
/** | ||
* Update an object in the database. This method is used to update only required fields of the object. | ||
* @param key The key of the object | ||
* @param volume The volume in which the object is stored | ||
* @param clazz The class of the object | ||
* @param transition The transition function which will be used to update the object | ||
* @param <T> The type of the object | ||
*/ | ||
public synchronized <T extends CloremObject> void update(@NonNull String key, @NonNull String volume,@NonNull Class<T> clazz,@NonNull Consumer<T> transition){ | ||
var obj = clazz.cast(get(key,volume)); | ||
transition.accept(obj); | ||
if (key.equals(obj.getKey()) && volume.equals(obj.getVolume())) | ||
update(obj); | ||
else { | ||
delete(key,volume); | ||
put(obj); | ||
} | ||
} | ||
|
||
/** | ||
* Delete an object from the database. | ||
* @param key The key of the object | ||
* @param volume The volume in which the object is stored | ||
*/ | ||
public synchronized void delete(@NonNull String key,@NonNull String volume){ | ||
var volumeDir = new File(databaseDir,volume); | ||
var obj = new File(volumeDir,key); | ||
if (volumeDir.isDirectory() && obj.exists()) | ||
obj.delete(); | ||
else | ||
throw new IllegalArgumentException("The volume or the object does not exist"); | ||
} | ||
|
||
/** | ||
* Query the database. This method returns a list of objects which satisfy the condition. | ||
* @param volume The volume in which the objects are stored | ||
* @param clazz The class of the objects | ||
* @param condition The condition which the objects must satisfy. Returns true if the object is to be included in the list. | ||
* @param <T> The type of the objects | ||
* @return A list of objects which satisfy the condition | ||
*/ | ||
public <T extends CloremObject> List<T> query(@NonNull String volume,@NonNull Class<T> clazz, @NonNull Predicate<T> condition){ | ||
var files = new File(databaseDir,volume).listFiles(); | ||
if (files == null) | ||
throw new RuntimeException("The volume does not exist"); | ||
else { | ||
var list = new ArrayList<T>(); | ||
for (File file : files) { | ||
var obj = get(file.getName(),volume); | ||
try { | ||
if (condition.test(clazz.cast(obj))) | ||
list.add(clazz.cast(obj)); | ||
} catch (ClassCastException ignored){} | ||
} | ||
return list; | ||
} | ||
} | ||
|
||
/** | ||
* List all the objects in a volume. | ||
* @param volume The volume in which the objects are stored | ||
* @return A list of objects | ||
*/ | ||
public List<Object> listObjects(@NonNull String volume){ | ||
return CloremUtils.listObjects(new File(databaseDir,volume)); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
CloremDB/src/main/java/db/clorabase/clorem/CloremObject.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package db.clorabase.clorem; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* This interface is implemented by all the objects which are to be saved in the database. | ||
* The objects must implement this interface to be saved in the database. | ||
* | ||
* @author author Rahil khan | ||
* @version 1.0 | ||
* @since 1.0 | ||
*/ | ||
public interface CloremObject extends Serializable { | ||
|
||
String getKey(); | ||
String getVolume(); | ||
} |
50 changes: 50 additions & 0 deletions
50
CloremDB/src/main/java/db/clorabase/clorem/CloremUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package db.clorabase.clorem; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.FileNotFoundException; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.io.ObjectInputStream; | ||
import java.io.ObjectOutputStream; | ||
import java.io.UncheckedIOException; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public class CloremUtils { | ||
|
||
protected static void writeObject(Object object, File file){ | ||
try { | ||
var os = new ObjectOutputStream(new FileOutputStream(file)); | ||
os.writeObject(object); | ||
os.close(); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
|
||
} | ||
|
||
protected static Object readObject(File file){ | ||
try { | ||
var in = new ObjectInputStream(new FileInputStream(file)); | ||
var object = in.readObject(); | ||
in.close(); | ||
return object; | ||
} catch (IOException | ClassNotFoundException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
protected static List<Object> listObjects(File volume){ | ||
var files = volume.listFiles(); | ||
if (files == null) | ||
throw new RuntimeException("The volume does not exist"); | ||
else { | ||
var objects = new Object[files.length]; | ||
for (int i = 0; i < files.length; i++) { | ||
objects[i] = readObject(files[i]); | ||
} | ||
return Arrays.asList(objects); | ||
} | ||
} | ||
} |