-
Notifications
You must be signed in to change notification settings - Fork 0
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
ElinRin
committed
Mar 12, 2015
0 parents
commit 5d7501e
Showing
23 changed files
with
1,169 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,15 @@ | ||
package ru.fizteh.fivt.students.elina_denisova.j_unit; | ||
|
||
public class HandlerException { | ||
public static void handler(String message, Throwable cause) { | ||
System.err.println(message + ". " + cause.getMessage()); | ||
System.exit(1); | ||
} | ||
public static void handler(Throwable cause) { | ||
System.err.println(cause.getMessage()); | ||
System.exit(1); | ||
} | ||
|
||
} | ||
|
||
|
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,40 @@ | ||
package ru.fizteh.fivt.students.elina_denisova.j_unit; | ||
|
||
import ru.fizteh.fivt.students.elina_denisova.j_unit.commands.Commands; | ||
|
||
import java.util.NoSuchElementException; | ||
import java.util.Scanner; | ||
|
||
public class InteractiveParse { | ||
public static void parse(MyTableProvider directory) { | ||
Scanner in = new Scanner(System.in); | ||
try { | ||
while (true) { | ||
System.out.print("$ "); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
String s; | ||
s = in.nextLine(); | ||
s = s.trim(); | ||
String[] current = s.split("\\s+"); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
for (int i = 0; i < current.length; ++i) { | ||
current[i].trim(); | ||
} | ||
try { | ||
Commands command = Commands.fromString(current); | ||
command.execute(directory); | ||
} catch (NoSuchElementException e) { | ||
System.err.println(e.getMessage()); | ||
} | ||
} | ||
} catch (IllegalMonitorStateException e) { | ||
in.close(); | ||
System.out.println("Goodbye"); | ||
System.exit(0); | ||
} catch (NoSuchElementException e) { | ||
System.err.println(e.getMessage()); | ||
} catch (Exception e) { | ||
in.close(); | ||
HandlerException.handler(e); | ||
} | ||
in.close(); | ||
} | ||
} |
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,316 @@ | ||
package ru.fizteh.fivt.students.elina_denisova.j_unit; | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
import ru.fizteh.fivt.storage.strings.Table; | ||
|
||
import java.io.*; | ||
import java.nio.file.DirectoryNotEmptyException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class MyTable implements Table { | ||
|
||
private Path mainDir; | ||
private Map<String, Map<String, String>> databases; | ||
private static Map<Integer, ArrayList<String>> changes = new HashMap<>(); | ||
private int numberChanges = 0; | ||
|
||
public static final int COUNT_OBJECT = 16; | ||
public static final int COMMON_CONSTANT_INDEX = 100; | ||
public static final String ENCODING = "UTF-8"; | ||
public static final String SUF_DIR = ".dir"; | ||
public static final String SUF_FILE = ".dat"; | ||
|
||
public MyTable(File tableDir) { | ||
try { | ||
databases = new HashMap<>(); | ||
mainDir = tableDir.toPath(); | ||
|
||
for (int i = 0; i < COUNT_OBJECT; i++) { | ||
File subDir = new File(tableDir, i + SUF_DIR); | ||
for (int j = 0; j < COUNT_OBJECT; j++) { | ||
File dbFile = new File(subDir, j + SUF_FILE); | ||
if (dbFile.exists()) { | ||
String adds = index(i, j); | ||
databases.put(adds, new HashMap<String, String>()); | ||
readFromFile(dbFile, databases.get(adds)); | ||
} | ||
} | ||
} | ||
} catch (IllegalArgumentException e) { | ||
HandlerException.handler(e); | ||
} | ||
} | ||
|
||
public boolean containsKey(String adds) { | ||
return databases.containsKey(adds); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return mainDir.toString(); | ||
}; | ||
|
||
private String pathname(String key) { | ||
int hashCode = Math.abs(key.hashCode()); | ||
int dir = hashCode % COUNT_OBJECT; | ||
int file = hashCode / COUNT_OBJECT % COUNT_OBJECT; | ||
return index(dir, file); | ||
} | ||
|
||
private String index(int i, int j) { | ||
return Integer.toString(i * COMMON_CONSTANT_INDEX + j); | ||
} | ||
|
||
@Override | ||
public String get(String key) throws IllegalArgumentException { | ||
if (key != null) { | ||
String adds = pathname(key); | ||
return databases.get(adds).get(key); | ||
} else { | ||
throw new IllegalArgumentException("get: Haven't key. "); | ||
} | ||
} | ||
|
||
@Override | ||
public String put(String key, String value) { | ||
if ((key != null) || (value != null)) { | ||
String adds = pathname(key); | ||
if (!databases.containsKey(adds)) { | ||
databases.put(adds, new HashMap<String, String>()); | ||
} | ||
|
||
String oldValue = databases.get(adds).get(key); | ||
databases.get(adds).put(key, value); | ||
numberChanges++; | ||
changes.put(numberChanges, new ArrayList<String>()); | ||
changes.get(numberChanges).add("put"); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
changes.get(numberChanges).add(key); | ||
changes.get(numberChanges).add(value); | ||
if (oldValue == null) { | ||
changes.get(numberChanges).add("new"); | ||
} else { | ||
changes.get(numberChanges).add(oldValue); | ||
} | ||
return oldValue; | ||
} else { | ||
throw new IllegalArgumentException("put: Haven't key or value. "); | ||
} | ||
} | ||
|
||
@Override | ||
public String remove(String key) { | ||
if (key != null) { | ||
String adds = pathname(key); | ||
if (!databases.containsKey(adds)) { | ||
return null; | ||
} else { | ||
String oldValue = databases.get(adds).get(key); | ||
databases.get(adds).remove(key); | ||
numberChanges++; | ||
changes.put(numberChanges, new ArrayList<String>()); | ||
changes.get(numberChanges).add("remove"); | ||
changes.get(numberChanges).add(key); | ||
changes.get(numberChanges).add(oldValue); | ||
return oldValue; | ||
} | ||
} else { | ||
throw new IllegalArgumentException("get: Haven't key. "); | ||
} | ||
} | ||
|
||
@Override | ||
public int size() { | ||
int answer = 0; | ||
for (int i = 0; i < COUNT_OBJECT; i++) { | ||
for (int j = 0; j < COUNT_OBJECT; j++) { | ||
String adds = index(i, j); | ||
if (databases.containsKey(adds)) { | ||
answer += databases.get(adds).size(); | ||
} | ||
} | ||
} | ||
return answer; | ||
} | ||
|
||
@Override | ||
public int commit() { | ||
numberChanges = 0; | ||
changes = new HashMap<>(); | ||
|
||
int count = 0; | ||
for (int i = 0; i < COUNT_OBJECT; i++) { | ||
for (int j = 0; j < COUNT_OBJECT; j++) { | ||
String adds = index(i, j); | ||
if (databases.containsKey(adds)) { | ||
File directory = new File(mainDir.toString(), i + SUF_DIR); | ||
if (!directory.exists()) { | ||
if (!directory.mkdir()) { | ||
throw new UnsupportedOperationException("ParserCommands.commandsExecution.put:" | ||
This comment has been minimized.
Sorry, something went wrong. |
||
+ " Unable to create directories in working catalog"); | ||
} | ||
} | ||
File dataBaseOld = new File(directory, j + SUF_FILE); | ||
if (dataBaseOld.exists()) { | ||
try { | ||
Files.delete(dataBaseOld.toPath()); | ||
} catch (IOException e) { | ||
throw new RuntimeException("writeInFile: Can't overwrite file"); | ||
} | ||
} | ||
|
||
if (!dataBaseOld.exists()) { | ||
try { | ||
if (!dataBaseOld.createNewFile()) { | ||
throw new IOException(); | ||
} | ||
} catch (IOException | NullPointerException e) { | ||
throw new UnsupportedOperationException("ParserCommands.commandsExecution.put:" | ||
+ " Unable to create database files in working catalog"); | ||
} | ||
} | ||
try (RandomAccessFile dbFile = new RandomAccessFile(dataBaseOld, "rw")) { | ||
for (Map.Entry<String, String> current : databases.get(adds).entrySet()) { | ||
count++; | ||
writeNext(dbFile, current.getKey()); | ||
writeNext(dbFile, current.getValue()); | ||
} | ||
} catch (FileNotFoundException e) { | ||
throw new RuntimeException("writeInFile: File not found"); | ||
} catch (IOException e) { | ||
throw new RuntimeException("writeInFile: Can't write to file.", e); | ||
} | ||
|
||
if (databases.get(adds).size() == 0) { | ||
File subDir = new File(mainDir.toString(), i + SUF_DIR); | ||
File dbFile = new File(subDir, j + SUF_FILE); | ||
try { | ||
if (dbFile.exists()) { | ||
Files.delete(dbFile.toPath()); | ||
} | ||
} catch (IOException e) { | ||
throw new IllegalStateException("remove: " | ||
+ "Cannot delete database file. ", e); | ||
} | ||
databases.remove(adds); | ||
|
||
int k = 0; | ||
for (int file = 0; file < COUNT_OBJECT; file++) { | ||
String variableAdds = index(i, file); | ||
if (databases.containsKey(variableAdds)) { | ||
k++; | ||
} | ||
} | ||
if (k == 0) { | ||
try { | ||
Files.delete(subDir.toPath()); | ||
} catch (DirectoryNotEmptyException e) { | ||
throw new IllegalStateException("remove: Cannot remove table subdirectory. " | ||
+ "Redundant files", e); | ||
} catch (IOException e) { | ||
throw new IllegalStateException("remove: " | ||
+ "Cannot delete database subdirectory", e); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return count; | ||
|
||
} | ||
|
||
private void writeNext(RandomAccessFile dbFile, String word) throws IOException { | ||
try { | ||
dbFile.writeInt(word.getBytes(ENCODING).length); | ||
dbFile.write(word.getBytes(ENCODING)); | ||
} catch (UnsupportedEncodingException e) { | ||
throw new RuntimeException("writeNext: Don't supported encoding " + ENCODING + ". "); | ||
} catch (IOException e) { | ||
throw new RuntimeException("writeNext: Can't write to database. ", e); | ||
} | ||
} | ||
public void readFromFile(File dbFileName, Map<String, String> data) throws IllegalArgumentException { | ||
try (RandomAccessFile file = new RandomAccessFile(dbFileName.toString(), "r")) { | ||
|
||
if (file.length() > 0) { | ||
while (file.getFilePointer() < file.length()) { | ||
String key = readNext(file); | ||
String value = readNext(file); | ||
if (data.containsKey(key)) { | ||
throw new IllegalArgumentException("readFromFile: Two same keys in database file"); | ||
} | ||
data.put(key, value); | ||
} | ||
} | ||
} catch (UnsupportedEncodingException | IllegalArgumentException | FileNotFoundException e) { | ||
throw new RuntimeException(e); | ||
} catch (IOException e) { | ||
throw new RuntimeException(" readFromFile: Problems with reading from database file " + e.toString()); | ||
} catch (Exception e) { | ||
throw new RuntimeException("readFromFile: ", e); | ||
} | ||
} | ||
|
||
|
||
private String readNext(RandomAccessFile dbFile) throws IOException { | ||
try { | ||
int wordLength = dbFile.readInt(); | ||
byte[] word = new byte[wordLength]; | ||
dbFile.read(word, 0, wordLength); | ||
return new String(word, ENCODING); | ||
} catch (UnsupportedEncodingException e) { | ||
throw new UnsupportedEncodingException("readNext: UTF-8 encoding is not supported"); | ||
} catch (IOException e) { | ||
throw new IOException(" readNext: Can't read from database " + e.toString()); | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public int rollback() { | ||
int count = 0; | ||
Map<Integer, ArrayList<String>> saveChanges = changes; | ||
for (int i = saveChanges.size(); i > 0; i--) { | ||
String[] com = new String[saveChanges.get(i).size()]; | ||
com = saveChanges.get(i).toArray(com); | ||
String message; | ||
if (com[0].equals("put")) { | ||
if (com[3].equals("new")) { | ||
message = remove(com[1]); | ||
} else { | ||
message = put(com[1], com[3]); | ||
} | ||
} | ||
if (com[0].equals("remove")) { | ||
put(com[1], com[2]); | ||
} | ||
count++; | ||
} | ||
numberChanges = 0; | ||
changes = new HashMap<>(); | ||
return count; | ||
} | ||
|
||
@Override | ||
public List<String> list() { | ||
List<String> listKey = new ArrayList<>(); | ||
for (int i = 0; i < COUNT_OBJECT; i++) { | ||
for (int j = 0; j < COUNT_OBJECT; j++) { | ||
String adds = index(i, j); | ||
if (databases.containsKey(adds)) { | ||
for (String key : databases.get(adds).keySet()) { | ||
listKey.add(key); | ||
} | ||
} | ||
} | ||
} return listKey; | ||
} | ||
|
||
public int unsavedChanges() { | ||
return numberChanges; | ||
} | ||
} |
Oops, something went wrong.
Вынести строку в константы класса