Code reformatted

This commit is contained in:
serso
2016-01-04 12:39:25 +01:00
parent 11bdcae2a8
commit 4eeeb1277e
794 changed files with 35363 additions and 35284 deletions

View File

@@ -22,14 +22,28 @@
package org.solovyev.acraanalyzer;
import org.apache.commons.cli.*;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.solovyev.common.collections.Collections.getFirstCollectionElement;
import static org.solovyev.common.text.Strings.isEmpty;
@@ -41,237 +55,237 @@ import static org.solovyev.common.text.Strings.isEmpty;
*/
public final class AcraAnalyzer {
private static final String NEW_LINE = System.getProperty("line.separator");
private static final String NEW_LINE = System.getProperty("line.separator");
public static void main(String[] args) throws ParseException, FileNotFoundException {
final Options options = new Options();
options.addOption("path", true, "Path to the ACRA reports");
options.addOption("file", true, "File name of MBOX file");
options.addOption("version", true, "Version of the app");
options.addOption("out", true, "Output file");
public static void main(String[] args) throws ParseException, FileNotFoundException {
final Options options = new Options();
options.addOption("path", true, "Path to the ACRA reports");
options.addOption("file", true, "File name of MBOX file");
options.addOption("version", true, "Version of the app");
options.addOption("out", true, "Output file");
final CommandLineParser parser = new GnuParser();
final CommandLine cmd = parser.parse(options, args);
final String path = cmd.getOptionValue("path");
final String file = cmd.getOptionValue("file");
final String version = cmd.getOptionValue("version");
final String out = cmd.getOptionValue("out");
final CommandLineParser parser = new GnuParser();
final CommandLine cmd = parser.parse(options, args);
final String path = cmd.getOptionValue("path");
final String file = cmd.getOptionValue("file");
final String version = cmd.getOptionValue("version");
final String out = cmd.getOptionValue("out");
if (isEmpty(path) && isEmpty(file)) {
throw new IllegalArgumentException("Either path or filename should be specified");
} else if (!isEmpty(path) && !isEmpty(file)) {
throw new IllegalArgumentException("Specify either path or filename");
} else {
final Map<String, List<AcraReport>> reports = new HashMap<String, List<AcraReport>>();
if (isEmpty(path) && isEmpty(file)) {
throw new IllegalArgumentException("Either path or filename should be specified");
} else if (!isEmpty(path) && !isEmpty(file)) {
throw new IllegalArgumentException("Specify either path or filename");
} else {
final Map<String, List<AcraReport>> reports = new HashMap<String, List<AcraReport>>();
if (!isEmpty(path)) {
scanFiles(path, reports, version);
} else {
scanMbox(file, reports, version);
}
if (!isEmpty(path)) {
scanFiles(path, reports, version);
} else {
scanMbox(file, reports, version);
}
PrintStream outIs;
if (!isEmpty(out)) {
final File outFile = new File(out);
outIs = new PrintStream(outFile);
System.out.println("Output will be written to " + outFile.getPath());
} else {
outIs = System.out;
}
PrintStream outIs;
if (!isEmpty(out)) {
final File outFile = new File(out);
outIs = new PrintStream(outFile);
System.out.println("Output will be written to " + outFile.getPath());
} else {
outIs = System.out;
}
final List<List<AcraReport>> sortedReports = new ArrayList<List<AcraReport>>(reports.size());
for (Map.Entry<String, List<AcraReport>> entry : reports.entrySet()) {
sortedReports.add(entry.getValue());
}
final List<List<AcraReport>> sortedReports = new ArrayList<List<AcraReport>>(reports.size());
for (Map.Entry<String, List<AcraReport>> entry : reports.entrySet()) {
sortedReports.add(entry.getValue());
}
Collections.sort(sortedReports, new Comparator<Collection<AcraReport>>() {
@Override
public int compare(Collection<AcraReport> lhs, Collection<AcraReport> rhs) {
if (lhs.size() == rhs.size()) {
return 0;
} else if (lhs.size() < rhs.size()) {
return 1;
} else {
return -1;
}
}
});
Collections.sort(sortedReports, new Comparator<Collection<AcraReport>>() {
@Override
public int compare(Collection<AcraReport> lhs, Collection<AcraReport> rhs) {
if (lhs.size() == rhs.size()) {
return 0;
} else if (lhs.size() < rhs.size()) {
return 1;
} else {
return -1;
}
}
});
if (!sortedReports.isEmpty()) {
for (Collection<AcraReport> sortedReport : sortedReports) {
final AcraReport report = getFirstCollectionElement(sortedReport);
outIs.println("Count: " + sortedReport.size());
outIs.println("App version: " + report.appVersion);
outIs.println("Android versions: " + getAndroidVersions(sortedReport));
outIs.println("Phones: " + getPhones(sortedReport));
outIs.println("Stack trace: " + report.stackTrace);
}
} else {
outIs.println("No ACRA reports found");
}
}
}
if (!sortedReports.isEmpty()) {
for (Collection<AcraReport> sortedReport : sortedReports) {
final AcraReport report = getFirstCollectionElement(sortedReport);
outIs.println("Count: " + sortedReport.size());
outIs.println("App version: " + report.appVersion);
outIs.println("Android versions: " + getAndroidVersions(sortedReport));
outIs.println("Phones: " + getPhones(sortedReport));
outIs.println("Stack trace: " + report.stackTrace);
}
} else {
outIs.println("No ACRA reports found");
}
}
}
@Nonnull
private static String getPhones(@Nonnull Collection<AcraReport> reports) {
final Set<String> versions = new HashSet<String>();
for (AcraReport report : reports) {
versions.add(report.brand + "/" + report.phoneModel);
}
return versions.toString();
}
@Nonnull
private static String getPhones(@Nonnull Collection<AcraReport> reports) {
final Set<String> versions = new HashSet<String>();
for (AcraReport report : reports) {
versions.add(report.brand + "/" + report.phoneModel);
}
return versions.toString();
}
@Nonnull
private static String getAndroidVersions(@Nonnull Collection<AcraReport> reports) {
final Set<String> versions = new HashSet<String>();
for (AcraReport report : reports) {
versions.add(report.androidVersion);
}
return versions.toString();
}
@Nonnull
private static String getAndroidVersions(@Nonnull Collection<AcraReport> reports) {
final Set<String> versions = new HashSet<String>();
for (AcraReport report : reports) {
versions.add(report.androidVersion);
}
return versions.toString();
}
private static void scanMbox(@Nonnull String filename, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File file = new File(filename);
if (!file.isDirectory()) {
Scanner scanner = null;
private static void scanMbox(@Nonnull String filename, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File file = new File(filename);
if (!file.isDirectory()) {
Scanner scanner = null;
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {
final AcraReport report = readReport(scanner);
putReport(reports, report, version);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
}
}
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {
final AcraReport report = readReport(scanner);
putReport(reports, report, version);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
}
}
private static void scanFiles(@Nonnull String path, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File directory = new File(path);
if (directory.isDirectory()) {
scanFiles(directory, reports, version);
}
}
private static void scanFiles(@Nonnull String path, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File directory = new File(path);
if (directory.isDirectory()) {
scanFiles(directory, reports, version);
}
}
private static void scanFiles(@Nonnull File directory, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
scanFiles(file, reports, version);
} else {
analyzeFile(file, reports, version);
}
}
}
}
private static void scanFiles(@Nonnull File directory, @Nonnull Map<String, List<AcraReport>> reports, @Nullable String version) {
final File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
scanFiles(file, reports, version);
} else {
analyzeFile(file, reports, version);
}
}
}
}
private static void analyzeFile(File file, Map<String, List<AcraReport>> reports, @Nullable String version) {
final AcraReport report = readReport(file);
putReport(reports, report, version);
}
private static void analyzeFile(File file, Map<String, List<AcraReport>> reports, @Nullable String version) {
final AcraReport report = readReport(file);
putReport(reports, report, version);
}
private static void putReport(@Nonnull Map<String, List<AcraReport>> reports, @Nonnull AcraReport report, @Nullable String version) {
if (!isEmpty(report.stackTrace) && (version == null || version.equals(report.appVersion))) {
List<AcraReport> acraReports = reports.get(report.stackTrace);
if (acraReports == null) {
acraReports = new ArrayList<AcraReport>();
reports.put(report.stackTrace, acraReports);
}
acraReports.add(report);
}
}
private static void putReport(@Nonnull Map<String, List<AcraReport>> reports, @Nonnull AcraReport report, @Nullable String version) {
if (!isEmpty(report.stackTrace) && (version == null || version.equals(report.appVersion))) {
List<AcraReport> acraReports = reports.get(report.stackTrace);
if (acraReports == null) {
acraReports = new ArrayList<AcraReport>();
reports.put(report.stackTrace, acraReports);
}
acraReports.add(report);
}
}
private static AcraReport readReport(@Nonnull File file) {
Scanner scanner = null;
private static AcraReport readReport(@Nonnull File file) {
Scanner scanner = null;
try {
scanner = new Scanner(file);
return readReport(scanner);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
try {
scanner = new Scanner(file);
return readReport(scanner);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
return new AcraReport();
}
return new AcraReport();
}
@Nonnull
private static AcraReport readReport(@Nonnull Scanner scanner) {
final AcraReport result = new AcraReport();
@Nonnull
private static AcraReport readReport(@Nonnull Scanner scanner) {
final AcraReport result = new AcraReport();
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
if (line.startsWith("STACK_TRACE")) {
result.stackTrace = readStackTrace(line.substring("STACK_TRACE=".length()), scanner);
break;
} else if (line.startsWith("ANDROID_VERSION")) {
result.androidVersion = line.substring("ANDROID_VERSION=".length());
} else if (line.startsWith("APP_VERSION_NAME")) {
result.appVersion = line.substring("APP_VERSION_NAME=".length());
} else if (line.startsWith("BRAND")) {
result.brand = line.substring("BRAND=".length());
} else if (line.startsWith("USER_COMMENT")) {
result.userComment = line.substring("USER_COMMENT=".length());
} else if (line.startsWith("PHONE_MODEL")) {
result.phoneModel = line.substring("PHONE_MODEL=".length());
}
}
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
if (line.startsWith("STACK_TRACE")) {
result.stackTrace = readStackTrace(line.substring("STACK_TRACE=".length()), scanner);
break;
} else if (line.startsWith("ANDROID_VERSION")) {
result.androidVersion = line.substring("ANDROID_VERSION=".length());
} else if (line.startsWith("APP_VERSION_NAME")) {
result.appVersion = line.substring("APP_VERSION_NAME=".length());
} else if (line.startsWith("BRAND")) {
result.brand = line.substring("BRAND=".length());
} else if (line.startsWith("USER_COMMENT")) {
result.userComment = line.substring("USER_COMMENT=".length());
} else if (line.startsWith("PHONE_MODEL")) {
result.phoneModel = line.substring("PHONE_MODEL=".length());
}
}
return result;
}
return result;
}
private static String readStackTrace(String firstLine, Scanner scanner) {
final StringBuilder sb = new StringBuilder();
sb.append(firstLine.trim()).append(newLine());
private static String readStackTrace(String firstLine, Scanner scanner) {
final StringBuilder sb = new StringBuilder();
sb.append(firstLine.trim()).append(newLine());
while (scanner.hasNextLine()) {
final String line = scanner.nextLine().trim();
if (isEmpty(line)) {
break;
} else {
sb.append(line).append(newLine());
}
}
while (scanner.hasNextLine()) {
final String line = scanner.nextLine().trim();
if (isEmpty(line)) {
break;
} else {
sb.append(line).append(newLine());
}
}
return sb.toString();
}
return sb.toString();
}
private static final class AcraReport {
private String userComment;
private String phoneModel;
private String brand;
private String appVersion;
private String androidVersion;
private String stackTrace = "";
public static String newLine() {
return NEW_LINE;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
private static final class AcraReport {
private String userComment;
private String phoneModel;
private String brand;
private String appVersion;
private String androidVersion;
private String stackTrace = "";
AcraReport that = (AcraReport) o;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!stackTrace.equals(that.stackTrace)) return false;
AcraReport that = (AcraReport) o;
return true;
}
if (!stackTrace.equals(that.stackTrace)) return false;
@Override
public int hashCode() {
return stackTrace.hashCode();
}
}
return true;
}
public static String newLine() {
return NEW_LINE;
}
@Override
public int hashCode() {
return stackTrace.hashCode();
}
}
}

View File

@@ -22,9 +22,6 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;
@@ -33,6 +30,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/30/11
@@ -40,142 +40,142 @@ import java.util.Map;
*/
public abstract class AbstractCalculatorMathRegistry<T extends MathEntity, P extends MathPersistenceEntity> implements CalculatorMathRegistry<T> {
@Nonnull
private final MathRegistry<T> mathRegistry;
@Nonnull
private final MathRegistry<T> mathRegistry;
@Nonnull
private final String prefix;
@Nonnull
private final String prefix;
@Nonnull
private final MathEntityDao<P> mathEntityDao;
@Nonnull
private final MathEntityDao<P> mathEntityDao;
protected AbstractCalculatorMathRegistry(@Nonnull MathRegistry<T> mathRegistry,
@Nonnull String prefix,
@Nonnull MathEntityDao<P> mathEntityDao) {
this.mathRegistry = mathRegistry;
this.prefix = prefix;
this.mathEntityDao = mathEntityDao;
}
protected AbstractCalculatorMathRegistry(@Nonnull MathRegistry<T> mathRegistry,
@Nonnull String prefix,
@Nonnull MathEntityDao<P> mathEntityDao) {
this.mathRegistry = mathRegistry;
this.prefix = prefix;
this.mathEntityDao = mathEntityDao;
}
@Nonnull
protected abstract Map<String, String> getSubstitutes();
@Nonnull
protected abstract Map<String, String> getSubstitutes();
@Nullable
@Override
public String getDescription(@Nonnull String mathEntityName) {
final String stringName;
@Nullable
@Override
public String getDescription(@Nonnull String mathEntityName) {
final String stringName;
final Map<String, String> substitutes = getSubstitutes();
final String substitute = substitutes.get(mathEntityName);
if (substitute == null) {
stringName = prefix + mathEntityName;
} else {
stringName = prefix + substitute;
}
final Map<String, String> substitutes = getSubstitutes();
final String substitute = substitutes.get(mathEntityName);
if (substitute == null) {
stringName = prefix + mathEntityName;
} else {
stringName = prefix + substitute;
}
return mathEntityDao.getDescription(stringName);
}
return mathEntityDao.getDescription(stringName);
}
public synchronized void load() {
final MathEntityPersistenceContainer<P> persistenceContainer = mathEntityDao.load();
public synchronized void load() {
final MathEntityPersistenceContainer<P> persistenceContainer = mathEntityDao.load();
final List<P> notCreatedEntities = new ArrayList<P>();
final List<P> notCreatedEntities = new ArrayList<P>();
if (persistenceContainer != null) {
for (P entity : persistenceContainer.getEntities()) {
if (!contains(entity.getName())) {
try {
final JBuilder<? extends T> builder = createBuilder(entity);
add(builder);
} catch (RuntimeException e) {
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
notCreatedEntities.add(entity);
}
}
}
}
if (persistenceContainer != null) {
for (P entity : persistenceContainer.getEntities()) {
if (!contains(entity.getName())) {
try {
final JBuilder<? extends T> builder = createBuilder(entity);
add(builder);
} catch (RuntimeException e) {
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
notCreatedEntities.add(entity);
}
}
}
}
try {
if (!notCreatedEntities.isEmpty()) {
final StringBuilder errorMessage = new StringBuilder(notCreatedEntities.size() * 100);
for (P notCreatedEntity : notCreatedEntities) {
errorMessage.append(notCreatedEntity).append("\n\n");
}
try {
if (!notCreatedEntities.isEmpty()) {
final StringBuilder errorMessage = new StringBuilder(notCreatedEntities.size() * 100);
for (P notCreatedEntity : notCreatedEntities) {
errorMessage.append(notCreatedEntity).append("\n\n");
}
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_message_dialog, MessageDialogData.newInstance(CalculatorMessages.newErrorMessage(CalculatorMessages.msg_007, errorMessage.toString()), null));
}
} catch (RuntimeException e) {
// just in case
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
}
}
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_message_dialog, MessageDialogData.newInstance(CalculatorMessages.newErrorMessage(CalculatorMessages.msg_007, errorMessage.toString()), null));
}
} catch (RuntimeException e) {
// just in case
Locator.getInstance().getLogger().error(null, e.getLocalizedMessage(), e);
}
}
@Nonnull
protected abstract JBuilder<? extends T> createBuilder(@Nonnull P entity);
@Nonnull
protected abstract JBuilder<? extends T> createBuilder(@Nonnull P entity);
@Override
public synchronized void save() {
final MathEntityPersistenceContainer<P> container = createPersistenceContainer();
@Override
public synchronized void save() {
final MathEntityPersistenceContainer<P> container = createPersistenceContainer();
for (T entity : this.getEntities()) {
if (!entity.isSystem()) {
final P persistenceEntity = transform(entity);
if (persistenceEntity != null) {
container.getEntities().add(persistenceEntity);
}
}
}
for (T entity : this.getEntities()) {
if (!entity.isSystem()) {
final P persistenceEntity = transform(entity);
if (persistenceEntity != null) {
container.getEntities().add(persistenceEntity);
}
}
}
this.mathEntityDao.save(container);
}
this.mathEntityDao.save(container);
}
@Nullable
protected abstract P transform(@Nonnull T entity);
@Nullable
protected abstract P transform(@Nonnull T entity);
@Nonnull
protected abstract MathEntityPersistenceContainer<P> createPersistenceContainer();
@Nonnull
protected abstract MathEntityPersistenceContainer<P> createPersistenceContainer();
@Nonnull
@Override
public List<T> getEntities() {
return mathRegistry.getEntities();
}
@Nonnull
@Override
public List<T> getEntities() {
return mathRegistry.getEntities();
}
@Nonnull
@Override
public List<T> getSystemEntities() {
return mathRegistry.getSystemEntities();
}
@Nonnull
@Override
public List<T> getSystemEntities() {
return mathRegistry.getSystemEntities();
}
@Override
public T add(@Nonnull JBuilder<? extends T> JBuilder) {
return mathRegistry.add(JBuilder);
}
@Override
public T add(@Nonnull JBuilder<? extends T> JBuilder) {
return mathRegistry.add(JBuilder);
}
@Override
public void remove(@Nonnull T var) {
mathRegistry.remove(var);
}
@Override
public void remove(@Nonnull T var) {
mathRegistry.remove(var);
}
@Nonnull
@Override
public List<String> getNames() {
return mathRegistry.getNames();
}
@Nonnull
@Override
public List<String> getNames() {
return mathRegistry.getNames();
}
@Override
public boolean contains(@Nonnull String name) {
return mathRegistry.contains(name);
}
@Override
public boolean contains(@Nonnull String name) {
return mathRegistry.contains(name);
}
@Override
public T get(@Nonnull String name) {
return mathRegistry.get(name);
}
@Override
public T get(@Nonnull String name) {
return mathRegistry.get(name);
}
@Override
public T getById(@Nonnull Integer id) {
return mathRegistry.getById(id);
}
@Override
public T getById(@Nonnull Integer id) {
return mathRegistry.getById(id);
}
}

View File

@@ -26,19 +26,19 @@ import javax.annotation.Nullable;
public abstract class AbstractFixableError implements FixableError {
@Nullable
private String fixCaption;
@Nullable
private String fixCaption;
protected AbstractFixableError() {
}
protected AbstractFixableError() {
}
protected AbstractFixableError(@Nullable String fixCaption) {
this.fixCaption = fixCaption;
}
protected AbstractFixableError(@Nullable String fixCaption) {
this.fixCaption = fixCaption;
}
@Nullable
@Override
public CharSequence getFixCaption() {
return fixCaption;
}
@Nullable
@Override
public CharSequence getFixCaption() {
return fixCaption;
}
}

View File

@@ -22,13 +22,13 @@
package org.solovyev.android.calculator;
import jscl.NumeralBase;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.text.Strings;
import jscl.NumeralBase;
/**
* User: serso
@@ -37,67 +37,67 @@ import org.solovyev.common.text.Strings;
*/
public abstract class AbstractNumberBuilder {
@Nonnull
protected final CalculatorEngine engine;
@Nonnull
protected final CalculatorEngine engine;
@Nullable
protected StringBuilder numberBuilder = null;
@Nullable
protected StringBuilder numberBuilder = null;
@Nullable
protected NumeralBase nb;
@Nullable
protected NumeralBase nb;
protected AbstractNumberBuilder(@Nonnull CalculatorEngine engine) {
this.engine = engine;
this.nb = engine.getNumeralBase();
}
protected AbstractNumberBuilder(@Nonnull CalculatorEngine engine) {
this.engine = engine;
this.nb = engine.getNumeralBase();
}
/**
* Method determines if we can continue to process current number
*
* @param mathTypeResult current math type result
* @return true if we can continue of processing of current number, if false - new number should be constructed
*/
protected boolean canContinue(@Nonnull MathType.Result mathTypeResult) {
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
!spaceBefore(mathTypeResult) &&
numeralBaseCheck(mathTypeResult) &&
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
return result;
}
/**
* Method determines if we can continue to process current number
*
* @param mathTypeResult current math type result
* @return true if we can continue of processing of current number, if false - new number should be constructed
*/
protected boolean canContinue(@Nonnull MathType.Result mathTypeResult) {
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
!spaceBefore(mathTypeResult) &&
numeralBaseCheck(mathTypeResult) &&
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
return result;
}
private boolean spaceBefore(@Nonnull MathType.Result mathTypeResult) {
return numberBuilder == null && Strings.isEmpty(mathTypeResult.getMatch().trim());
}
private boolean spaceBefore(@Nonnull MathType.Result mathTypeResult) {
return numberBuilder == null && Strings.isEmpty(mathTypeResult.getMatch().trim());
}
private boolean numeralBaseInTheStart(@Nonnull MathType mathType) {
return mathType != MathType.numeral_base || numberBuilder == null;
}
private boolean numeralBaseInTheStart(@Nonnull MathType mathType) {
return mathType != MathType.numeral_base || numberBuilder == null;
}
private boolean numeralBaseCheck(@Nonnull MathType.Result mathType) {
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
}
private boolean numeralBaseCheck(@Nonnull MathType.Result mathType) {
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
}
private boolean isSignAfterE(@Nonnull MathType.Result mathTypeResult) {
if (!isHexMode()) {
final String match = mathTypeResult.getMatch();
if ("".equals(match) || "-".equals(match) || "+".equals(match)) {
final StringBuilder localNb = numberBuilder;
if (localNb != null && localNb.length() > 0) {
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
return true;
}
}
}
}
return false;
}
private boolean isSignAfterE(@Nonnull MathType.Result mathTypeResult) {
if (!isHexMode()) {
final String match = mathTypeResult.getMatch();
if ("".equals(match) || "-".equals(match) || "+".equals(match)) {
final StringBuilder localNb = numberBuilder;
if (localNb != null && localNb.length() > 0) {
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
return true;
}
}
}
}
return false;
}
public boolean isHexMode() {
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
}
public boolean isHexMode() {
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
}
@Nonnull
protected NumeralBase getNumeralBase() {
return nb == null ? engine.getNumeralBase() : nb;
}
@Nonnull
protected NumeralBase getNumeralBase() {
return nb == null ? engine.getNumeralBase() : nb;
}
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator;
import jscl.NumeralBase;
import jscl.math.Generic;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.history.HistoryControl;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.history.HistoryControl;
import jscl.NumeralBase;
import jscl.math.Generic;
/**
* User: Solovyev_S
@@ -39,34 +39,34 @@ import org.solovyev.common.history.HistoryControl;
*/
public interface Calculator extends CalculatorEventContainer, HistoryControl<CalculatorHistoryState> {
void init();
void init();
/*
**********************************************************************
**********************************************************************
*
* CALCULATIONS
*
**********************************************************************
*/
void evaluate();
void evaluate();
void evaluate(@Nonnull Long sequenceId);
void evaluate(@Nonnull Long sequenceId);
void simplify();
void simplify();
@Nonnull
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
@Nonnull String expression);
@Nonnull
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
@Nonnull String expression);
@Nonnull
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nonnull Long sequenceId);
@Nonnull
CalculatorEventData evaluate(@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nonnull Long sequenceId);
void setCalculateOnFly(boolean calculateOnFly);
boolean isCalculateOnFly();
boolean isCalculateOnFly();
void setCalculateOnFly(boolean calculateOnFly);
/*
**********************************************************************
@@ -76,27 +76,27 @@ public interface Calculator extends CalculatorEventContainer, HistoryControl<Cal
**********************************************************************
*/
boolean isConversionPossible(@Nonnull Generic generic, @Nonnull NumeralBase from, @Nonnull NumeralBase to);
boolean isConversionPossible(@Nonnull Generic generic, @Nonnull NumeralBase from, @Nonnull NumeralBase to);
@Nonnull
CalculatorEventData convert(@Nonnull Generic generic, @Nonnull NumeralBase to);
@Nonnull
CalculatorEventData convert(@Nonnull Generic generic, @Nonnull NumeralBase to);
/*
**********************************************************************
*
* EVENTS
*
**********************************************************************
*/
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
/*
**********************************************************************
*
* EVENTS
*
**********************************************************************
*/
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Object source);
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Object source);
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Long sequenceId);
@Nonnull
CalculatorEventData fireCalculatorEvent(@Nonnull CalculatorEventType calculatorEventType, @Nullable Object data, @Nonnull Long sequenceId);
@Nonnull
PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException;
@Nonnull
PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException;
}

View File

@@ -32,10 +32,10 @@ import javax.annotation.Nullable;
*/
public interface CalculatorClipboard {
@Nullable
String getText();
@Nullable
String getText();
void setText(@Nonnull String text);
void setText(@Nonnull CharSequence text);
void setText(@Nonnull CharSequence text);
void setText(@Nonnull String text);
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import jscl.NumeralBase;
import jscl.math.Generic;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 24.09.12
@@ -34,16 +34,16 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorConversionEventData extends CalculatorEventData {
// display state on the moment of conversion
@Nonnull
CalculatorDisplayViewState getDisplayState();
// display state on the moment of conversion
@Nonnull
CalculatorDisplayViewState getDisplayState();
@Nonnull
NumeralBase getFromNumeralBase();
@Nonnull
NumeralBase getFromNumeralBase();
@Nonnull
NumeralBase getToNumeralBase();
@Nonnull
NumeralBase getToNumeralBase();
@Nonnull
Generic getValue();
@Nonnull
Generic getValue();
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import jscl.NumeralBase;
import jscl.math.Generic;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 24.09.12
@@ -34,93 +34,93 @@ import javax.annotation.Nonnull;
*/
public class CalculatorConversionEventDataImpl implements CalculatorConversionEventData {
@Nonnull
private CalculatorEventData calculatorEventData;
@Nonnull
private CalculatorEventData calculatorEventData;
@Nonnull
private NumeralBase fromNumeralBase;
@Nonnull
private NumeralBase fromNumeralBase;
@Nonnull
private NumeralBase toNumeralBase;
@Nonnull
private NumeralBase toNumeralBase;
@Nonnull
private Generic value;
@Nonnull
private Generic value;
@Nonnull
private CalculatorDisplayViewState displayState;
@Nonnull
private CalculatorDisplayViewState displayState;
private CalculatorConversionEventDataImpl() {
}
private CalculatorConversionEventDataImpl() {
}
@Nonnull
public static CalculatorConversionEventData newInstance(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull CalculatorDisplayViewState displayViewState) {
final CalculatorConversionEventDataImpl result = new CalculatorConversionEventDataImpl();
@Nonnull
public static CalculatorConversionEventData newInstance(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull CalculatorDisplayViewState displayViewState) {
final CalculatorConversionEventDataImpl result = new CalculatorConversionEventDataImpl();
result.calculatorEventData = calculatorEventData;
result.value = value;
result.displayState = displayViewState;
result.fromNumeralBase = from;
result.toNumeralBase = to;
result.calculatorEventData = calculatorEventData;
result.value = value;
result.displayState = displayViewState;
result.fromNumeralBase = from;
result.toNumeralBase = to;
return result;
}
return result;
}
@Override
public long getEventId() {
return calculatorEventData.getEventId();
}
@Override
public long getEventId() {
return calculatorEventData.getEventId();
}
@Override
@Nonnull
public Long getSequenceId() {
return calculatorEventData.getSequenceId();
}
@Override
@Nonnull
public Long getSequenceId() {
return calculatorEventData.getSequenceId();
}
@Override
public Object getSource() {
return calculatorEventData.getSource();
}
@Override
public Object getSource() {
return calculatorEventData.getSource();
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfter(that);
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfter(that);
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isSameSequence(that);
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isSameSequence(that);
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfterSequence(that);
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfterSequence(that);
}
@Nonnull
@Override
public CalculatorDisplayViewState getDisplayState() {
return this.displayState;
}
@Nonnull
@Override
public CalculatorDisplayViewState getDisplayState() {
return this.displayState;
}
@Override
@Nonnull
public NumeralBase getFromNumeralBase() {
return fromNumeralBase;
}
@Override
@Nonnull
public NumeralBase getFromNumeralBase() {
return fromNumeralBase;
}
@Override
@Nonnull
public NumeralBase getToNumeralBase() {
return toNumeralBase;
}
@Override
@Nonnull
public NumeralBase getToNumeralBase() {
return toNumeralBase;
}
@Override
@Nonnull
public Generic getValue() {
return value;
}
@Override
@Nonnull
public Generic getValue() {
return value;
}
}

View File

@@ -32,17 +32,18 @@ import javax.annotation.Nullable;
*/
public interface CalculatorDisplay extends CalculatorEventListener {
void setView(@Nonnull CalculatorDisplayView view);
void clearView(@Nonnull CalculatorDisplayView view);
void clearView(@Nonnull CalculatorDisplayView view);
@Nullable
CalculatorDisplayView getView();
@Nullable
CalculatorDisplayView getView();
@Nonnull
CalculatorDisplayViewState getViewState();
void setView(@Nonnull CalculatorDisplayView view);
void setViewState(@Nonnull CalculatorDisplayViewState viewState);
@Nonnull
CalculatorDisplayViewState getViewState();
@Nonnull
CalculatorEventData getLastEventData();
void setViewState(@Nonnull CalculatorDisplayViewState viewState);
@Nonnull
CalculatorEventData getLastEventData();
}

View File

@@ -31,26 +31,26 @@ import javax.annotation.Nonnull;
*/
public class CalculatorDisplayChangeEventDataImpl implements CalculatorDisplayChangeEventData {
@Nonnull
private final CalculatorDisplayViewState oldState;
@Nonnull
private final CalculatorDisplayViewState oldState;
@Nonnull
private final CalculatorDisplayViewState newState;
@Nonnull
private final CalculatorDisplayViewState newState;
public CalculatorDisplayChangeEventDataImpl(@Nonnull CalculatorDisplayViewState oldState, @Nonnull CalculatorDisplayViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
public CalculatorDisplayChangeEventDataImpl(@Nonnull CalculatorDisplayViewState oldState, @Nonnull CalculatorDisplayViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
@Nonnull
@Override
public CalculatorDisplayViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorDisplayViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorDisplayViewState getNewValue() {
return this.newState;
}
@Nonnull
@Override
public CalculatorDisplayViewState getNewValue() {
return this.newState;
}
}

View File

@@ -39,164 +39,160 @@ import static org.solovyev.android.calculator.CalculatorEventType.display_state_
*/
public class CalculatorDisplayImpl implements CalculatorDisplay {
@Nonnull
private final CalculatorEventHolder lastEvent;
@Nonnull
private final CalculatorEventHolder lastEvent;
@Nonnull
private final Object viewLock = new Object();
@Nonnull
private final Calculator calculator;
@Nullable
private CalculatorDisplayView view;
@Nonnull
private CalculatorDisplayViewState viewState = CalculatorDisplayViewStateImpl.newDefaultInstance();
@Nullable
private CalculatorDisplayView view;
public CalculatorDisplayImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
this.lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
this.calculator.addCalculatorEventListener(this);
}
@Nonnull
private final Object viewLock = new Object();
@Override
public void clearView(@Nonnull CalculatorDisplayView view) {
synchronized (viewLock) {
if (this.view == view) {
this.view = null;
}
}
}
@Nonnull
private CalculatorDisplayViewState viewState = CalculatorDisplayViewStateImpl.newDefaultInstance();
@Nullable
@Override
public CalculatorDisplayView getView() {
return this.view;
}
@Nonnull
private final Calculator calculator;
@Override
public void setView(@Nonnull CalculatorDisplayView view) {
synchronized (viewLock) {
this.view = view;
this.view.setState(viewState);
}
}
public CalculatorDisplayImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
this.lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
this.calculator.addCalculatorEventListener(this);
}
@Nonnull
@Override
public CalculatorDisplayViewState getViewState() {
return this.viewState;
}
@Override
public void setView(@Nonnull CalculatorDisplayView view) {
synchronized (viewLock) {
this.view = view;
this.view.setState(viewState);
}
}
@Override
public void setViewState(@Nonnull CalculatorDisplayViewState newViewState) {
synchronized (viewLock) {
final CalculatorDisplayViewState oldViewState = setViewState0(newViewState);
@Override
public void clearView(@Nonnull CalculatorDisplayView view) {
synchronized (viewLock) {
if (this.view == view) {
this.view = null;
}
}
}
this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState));
}
}
@Nullable
@Override
public CalculatorDisplayView getView() {
return this.view;
}
private void setViewStateForSequence(@Nonnull CalculatorDisplayViewState newViewState, @Nonnull Long sequenceId) {
synchronized (viewLock) {
final CalculatorDisplayViewState oldViewState = setViewState0(newViewState);
@Nonnull
@Override
public CalculatorDisplayViewState getViewState() {
return this.viewState;
}
this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState), sequenceId);
}
}
@Override
public void setViewState(@Nonnull CalculatorDisplayViewState newViewState) {
synchronized (viewLock) {
final CalculatorDisplayViewState oldViewState = setViewState0(newViewState);
// must be synchronized with viewLock
@Nonnull
private CalculatorDisplayViewState setViewState0(@Nonnull CalculatorDisplayViewState newViewState) {
final CalculatorDisplayViewState oldViewState = this.viewState;
this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState));
}
}
this.viewState = newViewState;
if (this.view != null) {
this.view.setState(newViewState);
}
return oldViewState;
}
private void setViewStateForSequence(@Nonnull CalculatorDisplayViewState newViewState, @Nonnull Long sequenceId) {
synchronized (viewLock) {
final CalculatorDisplayViewState oldViewState = setViewState0(newViewState);
@Override
@Nonnull
public CalculatorEventData getLastEventData() {
return lastEvent.getLastEventData();
}
this.calculator.fireCalculatorEvent(display_state_changed, new CalculatorDisplayChangeEventDataImpl(oldViewState, newViewState), sequenceId);
}
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(calculation_result, calculation_failed, calculation_cancelled, conversion_result, conversion_failed)) {
// must be synchronized with viewLock
@Nonnull
private CalculatorDisplayViewState setViewState0(@Nonnull CalculatorDisplayViewState newViewState) {
final CalculatorDisplayViewState oldViewState = this.viewState;
final CalculatorEventHolder.Result result = lastEvent.apply(calculatorEventData);
this.viewState = newViewState;
if (this.view != null) {
this.view.setState(newViewState);
}
return oldViewState;
}
if (result.isNewAfter()) {
switch (calculatorEventType) {
case conversion_failed:
processConversationFailed((CalculatorConversionEventData) calculatorEventData, (ConversionFailure) data);
break;
case conversion_result:
processConversationResult((CalculatorConversionEventData) calculatorEventData, (String) data);
break;
case calculation_result:
processCalculationResult((CalculatorEvaluationEventData) calculatorEventData, (CalculatorOutput) data);
break;
case calculation_cancelled:
processCalculationCancelled((CalculatorEvaluationEventData) calculatorEventData);
break;
case calculation_failed:
processCalculationFailed((CalculatorEvaluationEventData) calculatorEventData, (CalculatorFailure) data);
break;
}
}
}
}
@Override
@Nonnull
public CalculatorEventData getLastEventData() {
return lastEvent.getLastEventData();
}
private void processConversationFailed(@Nonnull CalculatorConversionEventData calculatorEventData,
@Nonnull ConversionFailure data) {
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getDisplayState().getOperation(), CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error)), calculatorEventData.getSequenceId());
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(calculation_result, calculation_failed, calculation_cancelled, conversion_result, conversion_failed)) {
}
final CalculatorEventHolder.Result result = lastEvent.apply(calculatorEventData);
private void processCalculationFailed(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull CalculatorFailure data) {
if (result.isNewAfter()) {
switch (calculatorEventType) {
case conversion_failed:
processConversationFailed((CalculatorConversionEventData) calculatorEventData, (ConversionFailure) data);
break;
case conversion_result:
processConversationResult((CalculatorConversionEventData) calculatorEventData, (String) data);
break;
case calculation_result:
processCalculationResult((CalculatorEvaluationEventData) calculatorEventData, (CalculatorOutput) data);
break;
case calculation_cancelled:
processCalculationCancelled((CalculatorEvaluationEventData) calculatorEventData);
break;
case calculation_failed:
processCalculationFailed((CalculatorEvaluationEventData) calculatorEventData, (CalculatorFailure) data);
break;
}
}
}
}
final CalculatorEvalException calculatorEvalException = data.getCalculationEvalException();
private void processConversationFailed(@Nonnull CalculatorConversionEventData calculatorEventData,
@Nonnull ConversionFailure data) {
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getDisplayState().getOperation(), CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error)), calculatorEventData.getSequenceId());
final String errorMessage;
if (calculatorEvalException != null) {
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
} else {
final CalculatorParseException calculationParseException = data.getCalculationParseException();
if (calculationParseException != null) {
errorMessage = calculationParseException.getLocalizedMessage();
} else {
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
}
}
}
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId());
}
private void processCalculationFailed(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull CalculatorFailure data) {
private void processCalculationCancelled(@Nonnull CalculatorEvaluationEventData calculatorEventData) {
final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
final CalculatorEvalException calculatorEvalException = data.getCalculationEvalException();
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId());
}
final String errorMessage;
if (calculatorEvalException != null) {
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
} else {
final CalculatorParseException calculationParseException = data.getCalculationParseException();
if (calculationParseException != null) {
errorMessage = calculationParseException.getLocalizedMessage();
} else {
errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
}
}
private void processCalculationResult(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull CalculatorOutput data) {
final String stringResult = data.getStringResult();
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0), calculatorEventData.getSequenceId());
}
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId());
}
private void processConversationResult(@Nonnull CalculatorConversionEventData calculatorEventData, @Nonnull String result) {
// add prefix
if (calculatorEventData.getFromNumeralBase() != calculatorEventData.getToNumeralBase()) {
result = calculatorEventData.getToNumeralBase().getJsclPrefix() + result;
}
private void processCalculationCancelled(@Nonnull CalculatorEvaluationEventData calculatorEventData) {
final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error);
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage), calculatorEventData.getSequenceId());
}
private void processCalculationResult(@Nonnull CalculatorEvaluationEventData calculatorEventData, @Nonnull CalculatorOutput data) {
final String stringResult = data.getStringResult();
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0), calculatorEventData.getSequenceId());
}
private void processConversationResult(@Nonnull CalculatorConversionEventData calculatorEventData, @Nonnull String result) {
// add prefix
if (calculatorEventData.getFromNumeralBase() != calculatorEventData.getToNumeralBase()) {
result = calculatorEventData.getToNumeralBase().getJsclPrefix() + result;
}
final CalculatorDisplayViewState displayState = calculatorEventData.getDisplayState();
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(displayState.getOperation(), displayState.getResult(), result, 0), calculatorEventData.getSequenceId());
}
final CalculatorDisplayViewState displayState = calculatorEventData.getDisplayState();
this.setViewStateForSequence(CalculatorDisplayViewStateImpl.newValidState(displayState.getOperation(), displayState.getResult(), result, 0), calculatorEventData.getSequenceId());
}
}

View File

@@ -31,8 +31,8 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorDisplayView {
void setState(@Nonnull CalculatorDisplayViewState state);
@Nonnull
CalculatorDisplayViewState getState();
@Nonnull
CalculatorDisplayViewState getState();
void setState(@Nonnull CalculatorDisplayViewState state);
}

View File

@@ -22,14 +22,14 @@
package org.solovyev.android.calculator;
import jscl.math.Generic;
import org.solovyev.android.calculator.jscl.JsclOperation;
import java.io.Serializable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import java.io.Serializable;
import jscl.math.Generic;
/**
* User: serso
@@ -38,22 +38,22 @@ import java.io.Serializable;
*/
public interface CalculatorDisplayViewState extends Serializable {
@Nonnull
String getText();
@Nonnull
String getText();
int getSelection();
int getSelection();
@Nullable
Generic getResult();
@Nullable
Generic getResult();
boolean isValid();
boolean isValid();
@Nullable
String getErrorMessage();
@Nullable
String getErrorMessage();
@Nonnull
JsclOperation getOperation();
@Nonnull
JsclOperation getOperation();
@Nullable
String getStringResult();
@Nullable
String getStringResult();
}

View File

@@ -22,13 +22,13 @@
package org.solovyev.android.calculator;
import jscl.math.Generic;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.text.Strings;
import jscl.math.Generic;
/**
* User: serso
@@ -38,28 +38,28 @@ import org.solovyev.common.text.Strings;
public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewState {
/*
**********************************************************************
**********************************************************************
*
* FIELDS
*
**********************************************************************
*/
@Nonnull
private JsclOperation operation = JsclOperation.numeric;
@Nonnull
private JsclOperation operation = JsclOperation.numeric;
@Nullable
private transient Generic result;
@Nullable
private transient Generic result;
@Nullable
private String stringResult = "";
@Nullable
private String stringResult = "";
private boolean valid = true;
private boolean valid = true;
@Nullable
private String errorMessage;
@Nullable
private String errorMessage;
private int selection = 0;
private int selection = 0;
/*
**********************************************************************
@@ -69,38 +69,38 @@ public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewStat
**********************************************************************
*/
private CalculatorDisplayViewStateImpl() {
}
private CalculatorDisplayViewStateImpl() {
}
@Nonnull
public static CalculatorDisplayViewState newDefaultInstance() {
return new CalculatorDisplayViewStateImpl();
}
@Nonnull
public static CalculatorDisplayViewState newDefaultInstance() {
return new CalculatorDisplayViewStateImpl();
}
@Nonnull
public static CalculatorDisplayViewState newErrorState(@Nonnull JsclOperation operation,
@Nonnull String errorMessage) {
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
calculatorDisplayState.valid = false;
calculatorDisplayState.errorMessage = errorMessage;
calculatorDisplayState.operation = operation;
return calculatorDisplayState;
}
@Nonnull
public static CalculatorDisplayViewState newErrorState(@Nonnull JsclOperation operation,
@Nonnull String errorMessage) {
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
calculatorDisplayState.valid = false;
calculatorDisplayState.errorMessage = errorMessage;
calculatorDisplayState.operation = operation;
return calculatorDisplayState;
}
@Nonnull
public static CalculatorDisplayViewState newValidState(@Nonnull JsclOperation operation,
@Nullable Generic result,
@Nonnull String stringResult,
int selection) {
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
calculatorDisplayState.valid = true;
calculatorDisplayState.result = result;
calculatorDisplayState.stringResult = stringResult;
calculatorDisplayState.operation = operation;
calculatorDisplayState.selection = selection;
@Nonnull
public static CalculatorDisplayViewState newValidState(@Nonnull JsclOperation operation,
@Nullable Generic result,
@Nonnull String stringResult,
int selection) {
final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl();
calculatorDisplayState.valid = true;
calculatorDisplayState.result = result;
calculatorDisplayState.stringResult = stringResult;
calculatorDisplayState.operation = operation;
calculatorDisplayState.selection = selection;
return calculatorDisplayState;
}
return calculatorDisplayState;
}
/*
**********************************************************************
@@ -110,43 +110,43 @@ public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewStat
**********************************************************************
*/
@Nonnull
@Override
public String getText() {
return Strings.getNotEmpty(isValid() ? stringResult : errorMessage, "");
}
@Nonnull
@Override
public String getText() {
return Strings.getNotEmpty(isValid() ? stringResult : errorMessage, "");
}
@Override
public int getSelection() {
return selection;
}
@Override
public int getSelection() {
return selection;
}
@Nullable
@Override
public Generic getResult() {
return this.result;
}
@Nullable
@Override
public Generic getResult() {
return this.result;
}
@Override
public boolean isValid() {
return this.valid;
}
@Override
public boolean isValid() {
return this.valid;
}
@Nullable
@Override
public String getErrorMessage() {
return this.errorMessage;
}
@Nullable
@Override
public String getErrorMessage() {
return this.errorMessage;
}
@Override
@Nullable
public String getStringResult() {
return stringResult;
}
@Override
@Nullable
public String getStringResult() {
return stringResult;
}
@Nonnull
@Override
public JsclOperation getOperation() {
return this.operation;
}
@Nonnull
@Override
public JsclOperation getOperation() {
return this.operation;
}
}

View File

@@ -33,84 +33,85 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorEditor extends CalculatorEventListener {
@Nonnull
String TAG = CalculatorEditor.class.getSimpleName();
@Nonnull
String TAG = CalculatorEditor.class.getSimpleName();
void setView(@Nonnull CalculatorEditorView view);
void clearView(@Nonnull CalculatorEditorView view);
void setView(@Nonnull CalculatorEditorView view);
@Nonnull
CalculatorEditorViewState getViewState();
void clearView(@Nonnull CalculatorEditorView view);
// updates state of view (view.setState())
void updateViewState();
@Nonnull
CalculatorEditorViewState getViewState();
void setViewState(@Nonnull CalculatorEditorViewState viewState);
void setViewState(@Nonnull CalculatorEditorViewState viewState);
// updates state of view (view.setState())
void updateViewState();
/*
**********************************************************************
**********************************************************************
*
* CURSOR CONTROL
*
**********************************************************************
*/
/**
* Method sets the cursor to the beginning
*/
@Nonnull
public CalculatorEditorViewState setCursorOnStart();
/**
* Method sets the cursor to the beginning
*/
@Nonnull
public CalculatorEditorViewState setCursorOnStart();
/**
* Method sets the cursor to the end
*/
@Nonnull
public CalculatorEditorViewState setCursorOnEnd();
/**
* Method sets the cursor to the end
*/
@Nonnull
public CalculatorEditorViewState setCursorOnEnd();
/**
* Method moves cursor to the left of current position
*/
@Nonnull
public CalculatorEditorViewState moveCursorLeft();
/**
* Method moves cursor to the left of current position
*/
@Nonnull
public CalculatorEditorViewState moveCursorLeft();
/**
* Method moves cursor to the right of current position
*/
@Nonnull
public CalculatorEditorViewState moveCursorRight();
/**
* Method moves cursor to the right of current position
*/
@Nonnull
public CalculatorEditorViewState moveCursorRight();
@Nonnull
CursorControl asCursorControl();
@Nonnull
CursorControl asCursorControl();
/*
**********************************************************************
*
* EDITOR OPERATIONS
*
**********************************************************************
*/
@Nonnull
CalculatorEditorViewState erase();
/*
**********************************************************************
*
* EDITOR OPERATIONS
*
**********************************************************************
*/
@Nonnull
CalculatorEditorViewState erase();
@Nonnull
CalculatorEditorViewState clear();
@Nonnull
CalculatorEditorViewState clear();
@Nonnull
CalculatorEditorViewState setText(@Nonnull String text);
@Nonnull
CalculatorEditorViewState setText(@Nonnull String text);
@Nonnull
CalculatorEditorViewState setText(@Nonnull String text, int selection);
@Nonnull
CalculatorEditorViewState setText(@Nonnull String text, int selection);
@Nonnull
CalculatorEditorViewState insert(@Nonnull String text);
@Nonnull
CalculatorEditorViewState insert(@Nonnull String text);
@Nonnull
CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset);
@Nonnull
CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset);
@Nonnull
CalculatorEditorViewState moveSelection(int offset);
@Nonnull
CalculatorEditorViewState moveSelection(int offset);
@Nonnull
CalculatorEditorViewState setSelection(int selection);
@Nonnull
CalculatorEditorViewState setSelection(int selection);
}

View File

@@ -31,32 +31,32 @@ import javax.annotation.Nonnull;
*/
public final class CalculatorEditorChangeEventData implements Change<CalculatorEditorViewState> {
@Nonnull
private CalculatorEditorViewState oldState;
@Nonnull
private CalculatorEditorViewState oldState;
@Nonnull
private CalculatorEditorViewState newState;
@Nonnull
private CalculatorEditorViewState newState;
private CalculatorEditorChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
private CalculatorEditorChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
return new CalculatorEditorChangeEventData(oldState, newState);
}
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
return new CalculatorEditorChangeEventData(oldState, newState);
}
@Nonnull
@Override
public CalculatorEditorViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorEditorViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorEditorViewState getNewValue() {
return this.newState;
}
@Nonnull
@Override
public CalculatorEditorViewState getNewValue() {
return this.newState;
}
}

View File

@@ -44,176 +44,162 @@ import static org.solovyev.android.calculator.CalculatorEventType.editor_state_c
*/
public class CalculatorEditorImpl implements CalculatorEditor {
@Nullable
private CalculatorEditorView view;
@Nonnull
private final Object viewLock = new Object();
@Nonnull
private final Calculator calculator;
@Nonnull
private final CalculatorEventHolder lastEventHolder;
@Nonnull
private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this);
@Nullable
private final TextProcessor<TextProcessorEditorResult, String> textProcessor;
@Nullable
private CalculatorEditorView view;
@Nonnull
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance();
@Nonnull
private final Object viewLock = new Object();
public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.calculator = calculator;
this.textProcessor = textProcessor;
this.calculator.addCalculatorEventListener(this);
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
}
@Nonnull
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance();
public static int correctSelection(int selection, @Nonnull CharSequence text) {
return correctSelection(selection, text.length());
}
@Nonnull
private final Calculator calculator;
public static int correctSelection(int selection, int textLength) {
int result = Math.max(selection, 0);
result = min(result, textLength);
return result;
}
@Nonnull
private final CalculatorEventHolder lastEventHolder;
@Override
public void setView(@Nonnull CalculatorEditorView view) {
synchronized (viewLock) {
this.view = view;
this.view.setState(lastViewState);
}
}
@Nonnull
private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this);
@Override
public void clearView(@Nonnull CalculatorEditorView view) {
synchronized (viewLock) {
if (this.view == view) {
this.view = null;
}
}
}
@Nullable
private final TextProcessor<TextProcessorEditorResult, String> textProcessor;
@Nonnull
@Override
public CalculatorEditorViewState getViewState() {
return lastViewState;
}
public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.calculator = calculator;
this.textProcessor = textProcessor;
this.calculator.addCalculatorEventListener(this);
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
}
@Override
public void setViewState(@Nonnull CalculatorEditorViewState newViewState) {
setViewState(newViewState, true);
}
@Override
public void setView(@Nonnull CalculatorEditorView view) {
synchronized (viewLock) {
this.view = view;
this.view.setState(lastViewState);
}
}
@Override
public void updateViewState() {
setViewState(this.lastViewState, false);
}
@Override
public void clearView(@Nonnull CalculatorEditorView view) {
synchronized (viewLock) {
if (this.view == view) {
this.view = null;
}
}
}
private void setViewState(@Nonnull CalculatorEditorViewState newViewState, boolean majorChanges) {
if (textProcessor != null) {
try {
final TextProcessorEditorResult result = textProcessor.process(newViewState.getText());
newViewState = CalculatorEditorViewStateImpl.newInstance(result.getCharSequence(), newViewState.getSelection() + result.getOffset());
} catch (CalculatorParseException e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
}
}
synchronized (viewLock) {
final CalculatorEditorViewState oldViewState = this.lastViewState;
@Nonnull
@Override
public CalculatorEditorViewState getViewState() {
return lastViewState;
}
this.lastViewState = newViewState;
if (this.view != null) {
this.view.setState(newViewState);
}
@Override
public void updateViewState() {
setViewState(this.lastViewState, false);
}
@Override
public void setViewState(@Nonnull CalculatorEditorViewState newViewState) {
setViewState(newViewState, true);
}
private void setViewState(@Nonnull CalculatorEditorViewState newViewState, boolean majorChanges) {
if (textProcessor != null) {
try {
final TextProcessorEditorResult result = textProcessor.process(newViewState.getText());
newViewState = CalculatorEditorViewStateImpl.newInstance(result.getCharSequence(), newViewState.getSelection() + result.getOffset());
} catch (CalculatorParseException e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
}
}
synchronized (viewLock) {
final CalculatorEditorViewState oldViewState = this.lastViewState;
this.lastViewState = newViewState;
if (this.view != null) {
this.view.setState(newViewState);
}
fireStateChangedEvent(majorChanges, oldViewState, newViewState);
}
}
private void fireStateChangedEvent(boolean majorChanges, @Nonnull CalculatorEditorViewState oldViewState, @Nonnull CalculatorEditorViewState newViewState) {
if (!Thread.holdsLock(viewLock)) throw new AssertionError();
if (majorChanges) {
calculator.fireCalculatorEvent(editor_state_changed, newChangeEventData(oldViewState, newViewState));
} else {
calculator.fireCalculatorEvent(editor_state_changed_light, newChangeEventData(oldViewState, newViewState));
}
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData);
if (result.isNewAfter()) {
switch (calculatorEventType) {
case use_history_state:
final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState) data;
final EditorHistoryState editorState = calculatorHistoryState.getEditorState();
this.setText(Strings.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition());
break;
}
}
}
fireStateChangedEvent(majorChanges, oldViewState, newViewState);
}
}
/*
**********************************************************************
**********************************************************************
*
* SELECTION
*
**********************************************************************
*/
@Nonnull
private CalculatorEditorViewState newSelectionViewState(int newSelection) {
if (this.lastViewState.getSelection() != newSelection) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection);
setViewState(result, false);
return result;
} else {
return this.lastViewState;
}
}
private void fireStateChangedEvent(boolean majorChanges, @Nonnull CalculatorEditorViewState oldViewState, @Nonnull CalculatorEditorViewState newViewState) {
if (!Thread.holdsLock(viewLock)) throw new AssertionError();
@Nonnull
public CalculatorEditorViewState setCursorOnStart() {
synchronized (viewLock) {
return newSelectionViewState(0);
}
}
if (majorChanges) {
calculator.fireCalculatorEvent(editor_state_changed, newChangeEventData(oldViewState, newViewState));
} else {
calculator.fireCalculatorEvent(editor_state_changed_light, newChangeEventData(oldViewState, newViewState));
}
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData);
@Nonnull
public CalculatorEditorViewState setCursorOnEnd() {
synchronized (viewLock) {
return newSelectionViewState(this.lastViewState.getText().length());
}
}
if (result.isNewAfter()) {
switch (calculatorEventType) {
case use_history_state:
final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState) data;
final EditorHistoryState editorState = calculatorHistoryState.getEditorState();
this.setText(Strings.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition());
break;
}
}
}
@Nonnull
public CalculatorEditorViewState moveCursorLeft() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() > 0) {
return newSelectionViewState(this.lastViewState.getSelection() - 1);
} else {
return this.lastViewState;
}
}
}
@Nonnull
private CalculatorEditorViewState newSelectionViewState(int newSelection) {
if (this.lastViewState.getSelection() != newSelection) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection);
setViewState(result, false);
return result;
} else {
return this.lastViewState;
}
}
@Nonnull
public CalculatorEditorViewState moveCursorRight() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
return newSelectionViewState(this.lastViewState.getSelection() + 1);
} else {
return this.lastViewState;
}
}
}
@Nonnull
public CalculatorEditorViewState setCursorOnStart() {
synchronized (viewLock) {
return newSelectionViewState(0);
}
}
@Nonnull
@Override
public CursorControl asCursorControl() {
return cursorControlAdapter;
}
@Nonnull
public CalculatorEditorViewState setCursorOnEnd() {
synchronized (viewLock) {
return newSelectionViewState(this.lastViewState.getText().length());
}
}
@Nonnull
public CalculatorEditorViewState moveCursorLeft() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() > 0) {
return newSelectionViewState(this.lastViewState.getSelection() - 1);
} else {
return this.lastViewState;
}
}
}
/*
**********************************************************************
@@ -223,143 +209,150 @@ public class CalculatorEditorImpl implements CalculatorEditor {
**********************************************************************
*/
@Nonnull
@Override
public CalculatorEditorViewState erase() {
synchronized (viewLock) {
int selection = this.lastViewState.getSelection();
final String text = this.lastViewState.getText();
if (selection > 0 && text.length() > 0 && selection <= text.length()) {
final StringBuilder newText = new StringBuilder(text.length() - 1);
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length()));
@Nonnull
public CalculatorEditorViewState moveCursorRight() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
return newSelectionViewState(this.lastViewState.getSelection() + 1);
} else {
return this.lastViewState;
}
}
}
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1);
setViewState(result);
return result;
} else {
return this.lastViewState;
}
}
}
@Nonnull
@Override
public CursorControl asCursorControl() {
return cursorControlAdapter;
}
@Nonnull
@Override
public CalculatorEditorViewState clear() {
synchronized (viewLock) {
return setText("");
}
}
@Nonnull
@Override
public CalculatorEditorViewState erase() {
synchronized (viewLock) {
int selection = this.lastViewState.getSelection();
final String text = this.lastViewState.getText();
if (selection > 0 && text.length() > 0 && selection <= text.length()) {
final StringBuilder newText = new StringBuilder(text.length() - 1);
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length()));
@Nonnull
@Override
public CalculatorEditorViewState setText(@Nonnull String text) {
synchronized (viewLock) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length());
setViewState(result);
return result;
}
}
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1);
setViewState(result);
return result;
} else {
return this.lastViewState;
}
}
}
@Nonnull
@Override
public CalculatorEditorViewState setText(@Nonnull String text, int selection) {
synchronized (viewLock) {
selection = correctSelection(selection, text);
@Nonnull
@Override
public CalculatorEditorViewState clear() {
synchronized (viewLock) {
return setText("");
}
}
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection);
setViewState(result);
return result;
}
}
@Nonnull
@Override
public CalculatorEditorViewState setText(@Nonnull String text) {
synchronized (viewLock) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length());
setViewState(result);
return result;
}
}
@Nonnull
@Override
public CalculatorEditorViewState insert(@Nonnull String text) {
synchronized (viewLock) {
return insert(text, 0);
}
}
@Nonnull
@Override
public CalculatorEditorViewState setText(@Nonnull String text, int selection) {
synchronized (viewLock) {
selection = correctSelection(selection, text);
@Nonnull
@Override
public CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset) {
synchronized (viewLock) {
final String oldText = lastViewState.getText();
final int selection = correctSelection(lastViewState.getSelection(), oldText);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection);
setViewState(result);
return result;
}
}
int newTextLength = text.length() + oldText.length();
final StringBuilder newText = new StringBuilder(newTextLength);
@Nonnull
@Override
public CalculatorEditorViewState insert(@Nonnull String text) {
synchronized (viewLock) {
return insert(text, 0);
}
}
newText.append(oldText.substring(0, selection));
newText.append(text);
newText.append(oldText.substring(selection));
@Nonnull
@Override
public CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset) {
synchronized (viewLock) {
final String oldText = lastViewState.getText();
final int selection = correctSelection(lastViewState.getSelection(), oldText);
int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection);
setViewState(result);
return result;
}
}
int newTextLength = text.length() + oldText.length();
final StringBuilder newText = new StringBuilder(newTextLength);
@Nonnull
@Override
public CalculatorEditorViewState moveSelection(int offset) {
synchronized (viewLock) {
int selection = this.lastViewState.getSelection() + offset;
newText.append(oldText.substring(0, selection));
newText.append(text);
newText.append(oldText.substring(selection));
return setSelection(selection);
}
}
int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection);
setViewState(result);
return result;
}
}
@Nonnull
@Override
public CalculatorEditorViewState setSelection(int selection) {
synchronized (viewLock) {
selection = correctSelection(selection, this.lastViewState.getText());
@Nonnull
@Override
public CalculatorEditorViewState moveSelection(int offset) {
synchronized (viewLock) {
int selection = this.lastViewState.getSelection() + offset;
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection);
setViewState(result, false);
return result;
}
}
return setSelection(selection);
}
}
public static int correctSelection(int selection, @Nonnull CharSequence text) {
return correctSelection(selection, text.length());
}
@Nonnull
@Override
public CalculatorEditorViewState setSelection(int selection) {
synchronized (viewLock) {
selection = correctSelection(selection, this.lastViewState.getText());
public static int correctSelection(int selection, int textLength) {
int result = Math.max(selection, 0);
result = min(result, textLength);
return result;
}
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection);
setViewState(result, false);
return result;
}
}
private static final class CursorControlAdapter implements CursorControl {
private static final class CursorControlAdapter implements CursorControl {
@Nonnull
private final CalculatorEditor calculatorEditor;
@Nonnull
private final CalculatorEditor calculatorEditor;
private CursorControlAdapter(@Nonnull CalculatorEditor calculatorEditor) {
this.calculatorEditor = calculatorEditor;
}
private CursorControlAdapter(@Nonnull CalculatorEditor calculatorEditor) {
this.calculatorEditor = calculatorEditor;
}
@Override
public void setCursorOnStart() {
this.calculatorEditor.setCursorOnStart();
}
@Override
public void setCursorOnStart() {
this.calculatorEditor.setCursorOnStart();
}
@Override
public void setCursorOnEnd() {
this.calculatorEditor.setCursorOnEnd();
}
@Override
public void setCursorOnEnd() {
this.calculatorEditor.setCursorOnEnd();
}
@Override
public void moveCursorLeft() {
this.calculatorEditor.moveCursorLeft();
}
@Override
public void moveCursorLeft() {
this.calculatorEditor.moveCursorLeft();
}
@Override
public void moveCursorRight() {
this.calculatorEditor.moveCursorRight();
}
}
@Override
public void moveCursorRight() {
this.calculatorEditor.moveCursorRight();
}
}
}

View File

@@ -31,5 +31,5 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorEditorView {
void setState(@Nonnull CalculatorEditorViewState viewState);
void setState(@Nonnull CalculatorEditorViewState viewState);
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import java.io.Serializable;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
@@ -33,11 +33,11 @@ import java.io.Serializable;
*/
public interface CalculatorEditorViewState extends Serializable {
@Nonnull
String getText();
@Nonnull
String getText();
@Nonnull
CharSequence getTextAsCharSequence();
@Nonnull
CharSequence getTextAsCharSequence();
int getSelection();
int getSelection();
}

View File

@@ -31,55 +31,55 @@ import javax.annotation.Nonnull;
*/
public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState {
@Nonnull
private CharSequence text = "";
@Nonnull
private CharSequence text = "";
private int selection = 0;
private int selection = 0;
private CalculatorEditorViewStateImpl() {
}
private CalculatorEditorViewStateImpl() {
}
public CalculatorEditorViewStateImpl(@Nonnull CalculatorEditorViewState viewState) {
this.text = viewState.getText();
this.selection = viewState.getSelection();
}
public CalculatorEditorViewStateImpl(@Nonnull CalculatorEditorViewState viewState) {
this.text = viewState.getText();
this.selection = viewState.getSelection();
}
@Nonnull
@Override
public String getText() {
return this.text.toString();
}
@Nonnull
public static CalculatorEditorViewState newDefaultInstance() {
return new CalculatorEditorViewStateImpl();
}
@Nonnull
@Override
public CharSequence getTextAsCharSequence() {
return this.text;
}
@Nonnull
public static CalculatorEditorViewState newSelection(@Nonnull CalculatorEditorViewState viewState, int newSelection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(viewState);
@Override
public int getSelection() {
return this.selection;
}
result.selection = newSelection;
@Nonnull
public static CalculatorEditorViewState newDefaultInstance() {
return new CalculatorEditorViewStateImpl();
}
return result;
}
@Nonnull
public static CalculatorEditorViewState newSelection(@Nonnull CalculatorEditorViewState viewState, int newSelection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(viewState);
@Nonnull
public static CalculatorEditorViewState newInstance(@Nonnull CharSequence text, int selection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl();
result.text = text;
result.selection = selection;
return result;
}
result.selection = newSelection;
@Nonnull
@Override
public String getText() {
return this.text.toString();
}
return result;
}
@Nonnull
@Override
public CharSequence getTextAsCharSequence() {
return this.text;
}
@Nonnull
public static CalculatorEditorViewState newInstance(@Nonnull CharSequence text, int selection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl();
result.text = text;
result.selection = selection;
return result;
}
@Override
public int getSelection() {
return this.selection;
}
}

View File

@@ -22,6 +22,10 @@
package org.solovyev.android.calculator;
import java.text.DecimalFormatSymbols;
import javax.annotation.Nonnull;
import jscl.AngleUnit;
import jscl.MathEngine;
import jscl.NumeralBase;
@@ -29,10 +33,6 @@ import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import javax.annotation.Nonnull;
import java.text.DecimalFormatSymbols;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -41,18 +41,18 @@ import java.text.DecimalFormatSymbols;
public interface CalculatorEngine {
/*
**********************************************************************
**********************************************************************
*
* INIT
*
**********************************************************************
*/
void init();
void init();
void reset();
void reset();
void softReset();
void softReset();
/*
**********************************************************************
@@ -62,24 +62,24 @@ public interface CalculatorEngine {
**********************************************************************
*/
@Nonnull
CalculatorMathRegistry<IConstant> getVarsRegistry();
@Nonnull
CalculatorMathRegistry<IConstant> getVarsRegistry();
@Nonnull
CalculatorMathRegistry<Function> getFunctionsRegistry();
@Nonnull
CalculatorMathRegistry<Function> getFunctionsRegistry();
@Nonnull
CalculatorMathRegistry<Operator> getOperatorsRegistry();
@Nonnull
CalculatorMathRegistry<Operator> getOperatorsRegistry();
@Nonnull
CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry();
@Nonnull
CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry();
@Nonnull
CalculatorMathEngine getMathEngine();
@Nonnull
CalculatorMathEngine getMathEngine();
@Deprecated
@Nonnull
MathEngine getMathEngine0();
@Deprecated
@Nonnull
MathEngine getMathEngine0();
/*
**********************************************************************
@@ -89,32 +89,32 @@ public interface CalculatorEngine {
**********************************************************************
*/
@Nonnull
String getMultiplicationSign();
@Nonnull
String getMultiplicationSign();
void setUseGroupingSeparator(boolean useGroupingSeparator);
void setMultiplicationSign(@Nonnull String multiplicationSign);
void setGroupingSeparator(char groupingSeparator);
void setUseGroupingSeparator(boolean useGroupingSeparator);
void setPrecision(@Nonnull Integer precision);
void setGroupingSeparator(char groupingSeparator);
void setRoundResult(@Nonnull Boolean round);
void setPrecision(@Nonnull Integer precision);
@Nonnull
AngleUnit getAngleUnits();
void setRoundResult(@Nonnull Boolean round);
void setAngleUnits(@Nonnull AngleUnit angleUnits);
@Nonnull
AngleUnit getAngleUnits();
@Nonnull
NumeralBase getNumeralBase();
void setAngleUnits(@Nonnull AngleUnit angleUnits);
void setNumeralBase(@Nonnull NumeralBase numeralBase);
@Nonnull
NumeralBase getNumeralBase();
void setMultiplicationSign(@Nonnull String multiplicationSign);
void setNumeralBase(@Nonnull NumeralBase numeralBase);
void setScienceNotation(@Nonnull Boolean scienceNotation);
void setScienceNotation(@Nonnull Boolean scienceNotation);
void setTimeout(@Nonnull Integer timeout);
void setTimeout(@Nonnull Integer timeout);
void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols);
void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols);
}

View File

@@ -29,7 +29,7 @@ package org.solovyev.android.calculator;
*/
public interface CalculatorEngineControl {
void evaluate();
void evaluate();
void simplify();
void simplify();
}

View File

@@ -22,6 +22,11 @@
package org.solovyev.android.calculator;
import java.text.DecimalFormatSymbols;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.MathEngine;
@@ -32,11 +37,6 @@ import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.text.DecimalFormatSymbols;
/**
* User: serso
* Date: 9/23/12
@@ -45,44 +45,44 @@ import java.text.DecimalFormatSymbols;
public class CalculatorEngineImpl implements CalculatorEngine {
/*
**********************************************************************
**********************************************************************
*
* CONSTANTS
*
**********************************************************************
*/
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
/*
**********************************************************************
*
* ENGINE/REGISTRIES
*
**********************************************************************
*/
@Nonnull
private final MathEngine engine;
/*
**********************************************************************
*
* ENGINE/REGISTRIES
*
**********************************************************************
*/
@Nonnull
private final MathEngine engine;
@Nonnull
private final CalculatorMathEngine mathEngine;
@Nonnull
private final CalculatorMathEngine mathEngine;
@Nonnull
private final CalculatorMathRegistry<IConstant> varsRegistry;
@Nonnull
private final CalculatorMathRegistry<IConstant> varsRegistry;
@Nonnull
private final CalculatorMathRegistry<Function> functionsRegistry;
@Nonnull
private final CalculatorMathRegistry<Function> functionsRegistry;
@Nonnull
private final CalculatorMathRegistry<Operator> operatorsRegistry;
@Nonnull
private final CalculatorMathRegistry<Operator> operatorsRegistry;
@Nonnull
private final CalculatorMathRegistry<Operator> postfixFunctionsRegistry;
@Nonnull
private final CalculatorMathRegistry<Operator> postfixFunctionsRegistry;
@Nonnull
private final Object lock;
@Nonnull
private final Object lock;
/*
**********************************************************************
@@ -93,73 +93,73 @@ public class CalculatorEngineImpl implements CalculatorEngine {
*/
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
@Nonnull
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
@Nonnull
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
public CalculatorEngineImpl(@Nonnull JsclMathEngine engine,
@Nonnull CalculatorMathRegistry<IConstant> varsRegistry,
@Nonnull CalculatorMathRegistry<Function> functionsRegistry,
@Nonnull CalculatorMathRegistry<Operator> operatorsRegistry,
@Nonnull CalculatorMathRegistry<Operator> postfixFunctionsRegistry,
@Nullable Object lock) {
public CalculatorEngineImpl(@Nonnull JsclMathEngine engine,
@Nonnull CalculatorMathRegistry<IConstant> varsRegistry,
@Nonnull CalculatorMathRegistry<Function> functionsRegistry,
@Nonnull CalculatorMathRegistry<Operator> operatorsRegistry,
@Nonnull CalculatorMathRegistry<Operator> postfixFunctionsRegistry,
@Nullable Object lock) {
this.engine = engine;
this.mathEngine = new JsclCalculatorMathEngine(engine);
this.engine = engine;
this.mathEngine = new JsclCalculatorMathEngine(engine);
this.engine.setRoundResult(true);
this.engine.setUseGroupingSeparator(true);
this.engine.setRoundResult(true);
this.engine.setUseGroupingSeparator(true);
this.varsRegistry = varsRegistry;
this.functionsRegistry = functionsRegistry;
this.operatorsRegistry = operatorsRegistry;
this.postfixFunctionsRegistry = postfixFunctionsRegistry;
this.lock = lock == null ? new Object() : lock;
}
this.varsRegistry = varsRegistry;
this.functionsRegistry = functionsRegistry;
this.operatorsRegistry = operatorsRegistry;
this.postfixFunctionsRegistry = postfixFunctionsRegistry;
this.lock = lock == null ? new Object() : lock;
}
/*
**********************************************************************
*
* REGISTRIES
*
**********************************************************************
*/
@Nonnull
@Override
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
return this.varsRegistry;
}
/*
**********************************************************************
*
* REGISTRIES
*
**********************************************************************
*/
@Nonnull
@Override
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
return this.varsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
return this.functionsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
return this.functionsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
return this.operatorsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
return this.operatorsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
return this.postfixFunctionsRegistry;
}
@Nonnull
@Override
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
return this.postfixFunctionsRegistry;
}
@Nonnull
@Override
public CalculatorMathEngine getMathEngine() {
return this.mathEngine;
}
@Nonnull
@Override
public CalculatorMathEngine getMathEngine() {
return this.mathEngine;
}
@Nonnull
@Override
public MathEngine getMathEngine0() {
return this.engine;
}
@Nonnull
@Override
public MathEngine getMathEngine0() {
return this.engine;
}
/*
**********************************************************************
@@ -169,40 +169,40 @@ public class CalculatorEngineImpl implements CalculatorEngine {
**********************************************************************
*/
@Override
public void init() {
synchronized (lock) {
reset();
}
}
@Override
public void init() {
synchronized (lock) {
reset();
}
}
@Override
public void reset() {
synchronized (lock) {
safeLoadRegistry(varsRegistry);
safeLoadRegistry(functionsRegistry);
safeLoadRegistry(operatorsRegistry);
safeLoadRegistry(postfixFunctionsRegistry);
}
}
@Override
public void reset() {
synchronized (lock) {
safeLoadRegistry(varsRegistry);
safeLoadRegistry(functionsRegistry);
safeLoadRegistry(operatorsRegistry);
safeLoadRegistry(postfixFunctionsRegistry);
}
}
private void safeLoadRegistry(@Nonnull CalculatorMathRegistry<?> registry) {
try {
registry.load();
} catch (Exception e) {
logException(e);
}
}
private void safeLoadRegistry(@Nonnull CalculatorMathRegistry<?> registry) {
try {
registry.load();
} catch (Exception e) {
logException(e);
}
}
private void logException(@Nonnull Exception e) {
final CalculatorLogger logger = Locator.getInstance().getLogger();
logger.error("Engine", e.getMessage(), e);
}
private void logException(@Nonnull Exception e) {
final CalculatorLogger logger = Locator.getInstance().getLogger();
logger.error("Engine", e.getMessage(), e);
}
@Override
public void softReset() {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.engine_preferences_changed, null);
}
@Override
public void softReset() {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.engine_preferences_changed, null);
}
/*
**********************************************************************
@@ -212,93 +212,93 @@ public class CalculatorEngineImpl implements CalculatorEngine {
**********************************************************************
*/
@Nonnull
@Override
public String getMultiplicationSign() {
return this.multiplicationSign;
}
@Nonnull
@Override
public String getMultiplicationSign() {
return this.multiplicationSign;
}
@Override
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
synchronized (lock) {
this.engine.setUseGroupingSeparator(true);
}
}
@Override
public void setMultiplicationSign(@Nonnull String multiplicationSign) {
this.multiplicationSign = multiplicationSign;
}
@Override
public void setGroupingSeparator(char groupingSeparator) {
synchronized (lock) {
this.engine.setGroupingSeparator(groupingSeparator);
}
}
@Override
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
synchronized (lock) {
this.engine.setUseGroupingSeparator(true);
}
}
@Override
public void setPrecision(@Nonnull Integer precision) {
synchronized (lock) {
this.engine.setPrecision(precision);
}
}
@Override
public void setGroupingSeparator(char groupingSeparator) {
synchronized (lock) {
this.engine.setGroupingSeparator(groupingSeparator);
}
}
@Override
public void setRoundResult(@Nonnull Boolean round) {
synchronized (lock) {
this.engine.setRoundResult(round);
}
}
@Override
public void setPrecision(@Nonnull Integer precision) {
synchronized (lock) {
this.engine.setPrecision(precision);
}
}
@Nonnull
@Override
public AngleUnit getAngleUnits() {
synchronized (lock) {
return this.engine.getAngleUnits();
}
}
@Override
public void setRoundResult(@Nonnull Boolean round) {
synchronized (lock) {
this.engine.setRoundResult(round);
}
}
@Override
public void setAngleUnits(@Nonnull AngleUnit angleUnits) {
synchronized (lock) {
this.engine.setAngleUnits(angleUnits);
}
}
@Nonnull
@Override
public AngleUnit getAngleUnits() {
synchronized (lock) {
return this.engine.getAngleUnits();
}
}
@Nonnull
@Override
public NumeralBase getNumeralBase() {
synchronized (lock) {
return this.engine.getNumeralBase();
}
}
@Override
public void setAngleUnits(@Nonnull AngleUnit angleUnits) {
synchronized (lock) {
this.engine.setAngleUnits(angleUnits);
}
}
@Override
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
synchronized (lock) {
this.engine.setNumeralBase(numeralBase);
}
}
@Nonnull
@Override
public NumeralBase getNumeralBase() {
synchronized (lock) {
return this.engine.getNumeralBase();
}
}
@Override
public void setMultiplicationSign(@Nonnull String multiplicationSign) {
this.multiplicationSign = multiplicationSign;
}
@Override
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
synchronized (lock) {
this.engine.setNumeralBase(numeralBase);
}
}
@Override
public void setScienceNotation(@Nonnull Boolean scienceNotation) {
synchronized (lock) {
this.engine.setScienceNotation(scienceNotation);
}
}
@Override
public void setScienceNotation(@Nonnull Boolean scienceNotation) {
synchronized (lock) {
this.engine.setScienceNotation(scienceNotation);
}
}
@Override
public void setTimeout(@Nonnull Integer timeout) {
this.timeout = timeout;
}
@Override
public void setTimeout(@Nonnull Integer timeout) {
this.timeout = timeout;
}
@Override
public void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols) {
synchronized (lock) {
this.engine.setDecimalGroupSymbols(decimalGroupSymbols);
}
}
@Override
public void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols) {
synchronized (lock) {
this.engine.setDecimalGroupSymbols(decimalGroupSymbols);
}
}
/*
**********************************************************************
@@ -308,49 +308,49 @@ public class CalculatorEngineImpl implements CalculatorEngine {
**********************************************************************
*/
private static final class JsclCalculatorMathEngine implements CalculatorMathEngine {
private static final class JsclCalculatorMathEngine implements CalculatorMathEngine {
@Nonnull
private final MathEngine mathEngine;
@Nonnull
private final MathEngine mathEngine;
private JsclCalculatorMathEngine(@Nonnull MathEngine mathEngine) {
this.mathEngine = mathEngine;
}
private JsclCalculatorMathEngine(@Nonnull MathEngine mathEngine) {
this.mathEngine = mathEngine;
}
@Nonnull
@Override
public String evaluate(@Nonnull String expression) throws ParseException {
return this.mathEngine.evaluate(expression);
}
@Nonnull
@Override
public String evaluate(@Nonnull String expression) throws ParseException {
return this.mathEngine.evaluate(expression);
}
@Nonnull
@Override
public String simplify(@Nonnull String expression) throws ParseException {
return this.mathEngine.simplify(expression);
}
@Nonnull
@Override
public String simplify(@Nonnull String expression) throws ParseException {
return this.mathEngine.simplify(expression);
}
@Nonnull
@Override
public String elementary(@Nonnull String expression) throws ParseException {
return this.mathEngine.elementary(expression);
}
@Nonnull
@Override
public String elementary(@Nonnull String expression) throws ParseException {
return this.mathEngine.elementary(expression);
}
@Nonnull
@Override
public Generic evaluateGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.evaluateGeneric(expression);
}
@Nonnull
@Override
public Generic evaluateGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.evaluateGeneric(expression);
}
@Nonnull
@Override
public Generic simplifyGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.simplifyGeneric(expression);
}
@Nonnull
@Override
public Generic simplifyGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.simplifyGeneric(expression);
}
@Nonnull
@Override
public Generic elementaryGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.elementaryGeneric(expression);
}
}
@Nonnull
@Override
public Generic elementaryGeneric(@Nonnull String expression) throws ParseException {
return this.mathEngine.elementaryGeneric(expression);
}
}
}

View File

@@ -22,14 +22,14 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageLevel;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 12/8/11
@@ -37,52 +37,52 @@ import java.util.Locale;
*/
public class CalculatorEvalException extends Exception implements Message {
@Nonnull
private final Message message;
@Nonnull
private final Message message;
@Nonnull
private final String expression;
@Nonnull
private final String expression;
public CalculatorEvalException(@Nonnull Message message, @Nonnull Throwable cause, String expression) {
super(cause);
this.message = message;
this.expression = expression;
}
public CalculatorEvalException(@Nonnull Message message, @Nonnull Throwable cause, String expression) {
super(cause);
this.message = message;
this.expression = expression;
}
@Nonnull
public String getExpression() {
return expression;
}
@Nonnull
public String getExpression() {
return expression;
}
@Nonnull
@Override
public String getMessageCode() {
return this.message.getMessageCode();
}
@Nonnull
@Override
public String getMessageCode() {
return this.message.getMessageCode();
}
@Nonnull
@Override
public List<Object> getParameters() {
return this.message.getParameters();
}
@Nonnull
@Override
public List<Object> getParameters() {
return this.message.getParameters();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return this.message.getMessageLevel();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return this.message.getMessageLevel();
}
@Override
@Nonnull
public String getLocalizedMessage() {
return this.message.getLocalizedMessage(Locale.getDefault());
}
@Override
@Nonnull
public String getLocalizedMessage() {
return this.message.getLocalizedMessage(Locale.getDefault());
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale);
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale);
}
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/20/12
@@ -33,9 +33,9 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public interface CalculatorEvaluationEventData extends CalculatorEventData {
@Nonnull
JsclOperation getOperation();
@Nonnull
JsclOperation getOperation();
@Nonnull
String getExpression();
@Nonnull
String getExpression();
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/20/12
@@ -33,63 +33,63 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData {
@Nonnull
private final CalculatorEventData calculatorEventData;
@Nonnull
private final CalculatorEventData calculatorEventData;
@Nonnull
private final JsclOperation operation;
@Nonnull
private final JsclOperation operation;
@Nonnull
private final String expression;
@Nonnull
private final String expression;
public CalculatorEvaluationEventDataImpl(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull JsclOperation operation,
@Nonnull String expression) {
this.calculatorEventData = calculatorEventData;
this.operation = operation;
this.expression = expression;
}
public CalculatorEvaluationEventDataImpl(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull JsclOperation operation,
@Nonnull String expression) {
this.calculatorEventData = calculatorEventData;
this.operation = operation;
this.expression = expression;
}
@Nonnull
@Override
public JsclOperation getOperation() {
return this.operation;
}
@Nonnull
@Override
public JsclOperation getOperation() {
return this.operation;
}
@Nonnull
@Override
public String getExpression() {
return this.expression;
}
@Nonnull
@Override
public String getExpression() {
return this.expression;
}
@Override
public long getEventId() {
return calculatorEventData.getEventId();
}
@Override
public long getEventId() {
return calculatorEventData.getEventId();
}
@Nonnull
@Override
public Long getSequenceId() {
return calculatorEventData.getSequenceId();
}
@Nonnull
@Override
public Long getSequenceId() {
return calculatorEventData.getSequenceId();
}
@Override
public Object getSource() {
return calculatorEventData.getSource();
}
@Override
public Object getSource() {
return calculatorEventData.getSource();
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfter(that);
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return calculatorEventData.isAfter(that);
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return this.calculatorEventData.isSameSequence(that);
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return this.calculatorEventData.isSameSequence(that);
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return this.calculatorEventData.isAfterSequence(that);
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return this.calculatorEventData.isAfterSequence(that);
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -34,46 +34,46 @@ import java.util.List;
*/
public interface CalculatorEventContainer {
void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener);
void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents);
void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents);
public static class CalculatorEvent {
public static class CalculatorEvent {
@Nonnull
private CalculatorEventData calculatorEventData;
@Nonnull
private CalculatorEventData calculatorEventData;
@Nonnull
private CalculatorEventType calculatorEventType;
@Nonnull
private CalculatorEventType calculatorEventType;
@Nullable
private Object data;
@Nullable
private Object data;
public CalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
this.calculatorEventData = calculatorEventData;
this.calculatorEventType = calculatorEventType;
this.data = data;
}
public CalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
this.calculatorEventData = calculatorEventData;
this.calculatorEventType = calculatorEventType;
this.data = data;
}
@Nonnull
public CalculatorEventData getCalculatorEventData() {
return calculatorEventData;
}
@Nonnull
public CalculatorEventData getCalculatorEventData() {
return calculatorEventData;
}
@Nonnull
public CalculatorEventType getCalculatorEventType() {
return calculatorEventType;
}
@Nonnull
public CalculatorEventType getCalculatorEventType() {
return calculatorEventType;
}
@Nullable
public Object getData() {
return data;
}
}
@Nullable
public Object getData() {
return data;
}
}
}

View File

@@ -32,19 +32,19 @@ import javax.annotation.Nullable;
*/
public interface CalculatorEventData {
// the higher id => the later event
long getEventId();
// the higher id => the later event
long getEventId();
// the higher id => the later event
@Nonnull
Long getSequenceId();
// the higher id => the later event
@Nonnull
Long getSequenceId();
@Nullable
Object getSource();
@Nullable
Object getSource();
boolean isAfter(@Nonnull CalculatorEventData that);
boolean isAfter(@Nonnull CalculatorEventData that);
boolean isSameSequence(@Nonnull CalculatorEventData that);
boolean isSameSequence(@Nonnull CalculatorEventData that);
boolean isAfterSequence(@Nonnull CalculatorEventData that);
boolean isAfterSequence(@Nonnull CalculatorEventData that);
}

View File

@@ -32,80 +32,78 @@ import javax.annotation.Nullable;
*/
class CalculatorEventDataImpl implements CalculatorEventData {
private static final long NO_SEQUENCE = -1L;
private static final long NO_SEQUENCE = -1L;
private final long eventId;
private final long eventId;
private final Object source;
@Nonnull
private Long sequenceId = NO_SEQUENCE;
@Nonnull
private Long sequenceId = NO_SEQUENCE;
private CalculatorEventDataImpl(long id, @Nonnull Long sequenceId, @Nullable Object source) {
this.eventId = id;
this.sequenceId = sequenceId;
this.source = source;
}
private final Object source;
@Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId) {
return new CalculatorEventDataImpl(id, sequenceId, null);
}
private CalculatorEventDataImpl(long id, @Nonnull Long sequenceId, @Nullable Object source) {
this.eventId = id;
this.sequenceId = sequenceId;
this.source = source;
}
@Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId, @Nonnull Object source) {
return new CalculatorEventDataImpl(id, sequenceId, source);
}
@Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId) {
return new CalculatorEventDataImpl(id, sequenceId, null);
}
@Override
public long getEventId() {
return this.eventId;
}
@Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId, @Nonnull Object source) {
return new CalculatorEventDataImpl(id, sequenceId, source);
}
@Nonnull
@Override
public Long getSequenceId() {
return this.sequenceId;
}
@Override
public long getEventId() {
return this.eventId;
}
@Override
public Object getSource() {
return this.source;
}
@Nonnull
@Override
public Long getSequenceId() {
return this.sequenceId;
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return this.eventId > that.getEventId();
}
@Override
public Object getSource() {
return this.source;
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId());
}
@Override
public boolean isAfter(@Nonnull CalculatorEventData that) {
return this.eventId > that.getEventId();
}
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId > that.getSequenceId();
}
@Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CalculatorEventDataImpl)) return false;
@Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId > that.getSequenceId();
}
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CalculatorEventDataImpl)) return false;
if (eventId != that.eventId) return false;
if (!sequenceId.equals(that.sequenceId))
return false;
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
return true;
}
if (eventId != that.eventId) return false;
if (!sequenceId.equals(that.sequenceId))
return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (eventId ^ (eventId >>> 32));
result = 31 * result + (sequenceId.hashCode());
return result;
}
@Override
public int hashCode() {
int result = (int) (eventId ^ (eventId >>> 32));
result = 31 * result + (sequenceId.hashCode());
return result;
}
}

View File

@@ -32,69 +32,69 @@ import javax.annotation.Nullable;
*/
public class CalculatorEventHolder {
@Nonnull
private volatile CalculatorEventData lastEventData;
@Nonnull
private volatile CalculatorEventData lastEventData;
public CalculatorEventHolder(@Nonnull CalculatorEventData lastEventData) {
this.lastEventData = lastEventData;
}
public CalculatorEventHolder(@Nonnull CalculatorEventData lastEventData) {
this.lastEventData = lastEventData;
}
@Nonnull
public synchronized CalculatorEventData getLastEventData() {
return lastEventData;
}
@Nonnull
public synchronized CalculatorEventData getLastEventData() {
return lastEventData;
}
@Nonnull
public synchronized Result apply(@Nonnull CalculatorEventData newEventData) {
final Result result = new Result(lastEventData, newEventData);
@Nonnull
public synchronized Result apply(@Nonnull CalculatorEventData newEventData) {
final Result result = new Result(lastEventData, newEventData);
if (result.isNewAfter()) {
this.lastEventData = newEventData;
}
if (result.isNewAfter()) {
this.lastEventData = newEventData;
}
return result;
}
return result;
}
public static class Result {
public static class Result {
@Nonnull
private final CalculatorEventData lastEventData;
@Nonnull
private final CalculatorEventData lastEventData;
@Nonnull
private final CalculatorEventData newEventData;
@Nonnull
private final CalculatorEventData newEventData;
@Nullable
private Boolean after = null;
@Nullable
private Boolean after = null;
@Nullable
private Boolean sameSequence = null;
@Nullable
private Boolean sameSequence = null;
public Result(@Nonnull CalculatorEventData lastEventData,
@Nonnull CalculatorEventData newEventData) {
this.lastEventData = lastEventData;
this.newEventData = newEventData;
}
public Result(@Nonnull CalculatorEventData lastEventData,
@Nonnull CalculatorEventData newEventData) {
this.lastEventData = lastEventData;
this.newEventData = newEventData;
}
public boolean isNewAfter() {
if (after == null) {
after = newEventData.isAfter(lastEventData);
}
return after;
}
public boolean isNewAfter() {
if (after == null) {
after = newEventData.isAfter(lastEventData);
}
return after;
}
public boolean isSameSequence() {
if (sameSequence == null) {
sameSequence = newEventData.isSameSequence(lastEventData);
}
return sameSequence;
}
public boolean isSameSequence() {
if (sameSequence == null) {
sameSequence = newEventData.isSameSequence(lastEventData);
}
return sameSequence;
}
public boolean isNewAfterSequence() {
return newEventData.isAfterSequence(lastEventData);
}
public boolean isNewAfterSequence() {
return newEventData.isAfterSequence(lastEventData);
}
public boolean isNewSameOrAfterSequence() {
return isSameSequence() || isNewAfterSequence();
}
}
public boolean isNewSameOrAfterSequence() {
return isSameSequence() || isNewAfterSequence();
}
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import java.util.EventListener;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.EventListener;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -34,6 +34,6 @@ import java.util.EventListener;
*/
public interface CalculatorEventListener extends EventListener {
void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data);
}

View File

@@ -32,7 +32,7 @@ import javax.annotation.Nonnull;
public enum CalculatorEventType {
/*
**********************************************************************
**********************************************************************
*
* CALCULATION
* org.solovyev.android.calculator.CalculatorEvaluationEventData
@@ -41,34 +41,34 @@ public enum CalculatorEventType {
*/
// @Nonnull CalculatorEditorViewState
manual_calculation_requested,
// @Nonnull CalculatorEditorViewState
manual_calculation_requested,
// @Nonnull org.solovyev.android.calculator.CalculatorOutput
calculation_result,
// @Nonnull org.solovyev.android.calculator.CalculatorOutput
calculation_result,
calculation_cancelled,
calculation_cancelled,
// @Nonnull org.solovyev.android.calculator.CalculatorFailure
calculation_failed,
// @Nonnull org.solovyev.android.calculator.CalculatorFailure
calculation_failed,
/*
**********************************************************************
*
* CONVERSION
* CalculatorConversionEventData
*
**********************************************************************
*/
conversion_started,
/*
**********************************************************************
*
* CONVERSION
* CalculatorConversionEventData
*
**********************************************************************
*/
conversion_started,
// @Nonnull String conversion result
conversion_result,
// @Nonnull String conversion result
conversion_result,
// @Nonnull ConversionFailure
conversion_failed,
// @Nonnull ConversionFailure
conversion_failed,
conversion_finished,
conversion_finished,
/*
**********************************************************************
@@ -78,12 +78,12 @@ public enum CalculatorEventType {
**********************************************************************
*/
// @Nonnull org.solovyev.android.calculator.CalculatorEditorChangeEventData
editor_state_changed,
editor_state_changed_light,
// @Nonnull org.solovyev.android.calculator.CalculatorEditorChangeEventData
editor_state_changed,
editor_state_changed_light,
// @Nonnull CalculatorDisplayChangeEventData
display_state_changed,
// @Nonnull CalculatorDisplayChangeEventData
display_state_changed,
/*
**********************************************************************
@@ -93,7 +93,7 @@ public enum CalculatorEventType {
**********************************************************************
*/
engine_preferences_changed,
engine_preferences_changed,
/*
**********************************************************************
@@ -103,13 +103,13 @@ public enum CalculatorEventType {
**********************************************************************
*/
// @Nonnull CalculatorHistoryState
history_state_added,
// @Nonnull CalculatorHistoryState
history_state_added,
// @Nonnull CalculatorHistoryState
use_history_state,
// @Nonnull CalculatorHistoryState
use_history_state,
clear_history_requested,
clear_history_requested,
/*
**********************************************************************
@@ -119,33 +119,33 @@ public enum CalculatorEventType {
**********************************************************************
*/
// @Nonnull IConstant
use_constant,
// @Nonnull IConstant
use_constant,
// @Nonnull Function
use_function,
// @Nonnull Function
use_function,
// @Nonnull Operator
use_operator,
// @Nonnull Operator
use_operator,
// @Nonnull IConstant
constant_added,
// @Nonnull IConstant
constant_added,
// @Nonnull Change<IConstant>
constant_changed,
// @Nonnull Change<IConstant>
constant_changed,
// @Nonnull IConstant
constant_removed,
// @Nonnull IConstant
constant_removed,
// @Nonnull Function
function_removed,
// @Nonnull Function
function_removed,
// @Nonnull Function
function_added,
// @Nonnull Function
function_added,
// @Nonnull Change<IFunction>
function_changed,
// @Nonnull Change<IFunction>
function_changed,
/*
**********************************************************************
@@ -155,55 +155,55 @@ public enum CalculatorEventType {
**********************************************************************
*/
// List<Message>
calculation_messages,
// List<Message>
calculation_messages,
show_history,
show_history_detached,
show_history,
show_history_detached,
show_functions,
show_functions_detached,
show_functions,
show_functions_detached,
show_vars,
show_vars_detached,
show_vars,
show_vars_detached,
open_app,
open_app,
show_operators,
show_operators_detached,
show_operators,
show_operators_detached,
show_settings,
show_settings_detached,
show_settings,
show_settings_detached,
show_like_dialog,
show_like_dialog,
show_create_var_dialog,
show_create_matrix_dialog,
show_create_function_dialog,
show_create_var_dialog,
show_create_matrix_dialog,
show_create_function_dialog,
/**
* {@link DialogData}
*/
show_message_dialog,
/**
* {@link DialogData}
*/
show_message_dialog,
plot_graph,
plot_graph,
/**
* {@link org.solovyev.android.calculator.plot.PlotData}
*/
plot_data_changed,
/**
* {@link org.solovyev.android.calculator.plot.PlotData}
*/
plot_data_changed,
//String
show_evaluation_error;
//String
show_evaluation_error;
public boolean isOfType(@Nonnull CalculatorEventType... types) {
for (CalculatorEventType type : types) {
if (this == type) {
return true;
}
}
public boolean isOfType(@Nonnull CalculatorEventType... types) {
for (CalculatorEventType type : types) {
if (this == type) {
return true;
}
}
return false;
}
return false;
}
}

View File

@@ -32,12 +32,12 @@ import javax.annotation.Nullable;
*/
public interface CalculatorFailure {
@Nonnull
Exception getException();
@Nonnull
Exception getException();
@Nullable
CalculatorParseException getCalculationParseException();
@Nullable
CalculatorParseException getCalculationParseException();
@Nullable
CalculatorEvalException getCalculationEvalException();
@Nullable
CalculatorEvalException getCalculationEvalException();
}

View File

@@ -31,33 +31,33 @@ import javax.annotation.Nonnull;
*/
public class CalculatorFailureImpl implements CalculatorFailure {
@Nonnull
private Exception exception;
@Nonnull
private Exception exception;
public CalculatorFailureImpl(@Nonnull Exception exception) {
this.exception = exception;
}
public CalculatorFailureImpl(@Nonnull Exception exception) {
this.exception = exception;
}
@Nonnull
@Override
public Exception getException() {
return this.exception;
}
@Nonnull
@Override
public Exception getException() {
return this.exception;
}
@Override
public CalculatorParseException getCalculationParseException() {
return exception instanceof CalculatorParseException ? (CalculatorParseException) exception : null;
}
@Override
public CalculatorParseException getCalculationParseException() {
return exception instanceof CalculatorParseException ? (CalculatorParseException) exception : null;
}
@Override
public CalculatorEvalException getCalculationEvalException() {
return exception instanceof CalculatorEvalException ? (CalculatorEvalException) exception : null;
}
@Override
public CalculatorEvalException getCalculationEvalException() {
return exception instanceof CalculatorEvalException ? (CalculatorEvalException) exception : null;
}
@Override
public String toString() {
return "CalculatorFailureImpl{" +
"exception=" + exception +
'}';
}
@Override
public String toString() {
return "CalculatorFailureImpl{" +
"exception=" + exception +
'}';
}
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator;
import jscl.AngleUnit;
import jscl.text.msg.Messages;
import org.solovyev.common.collections.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.collections.Collections;
import java.util.List;
import jscl.AngleUnit;
import jscl.text.msg.Messages;
/**
* User: serso
@@ -39,48 +39,48 @@ import java.util.List;
*/
public enum CalculatorFixableError implements FixableError {
must_be_rad(Messages.msg_23, Messages.msg_24, Messages.msg_25) {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setAngleUnits(AngleUnit.rad);
}
},
must_be_rad(Messages.msg_23, Messages.msg_24, Messages.msg_25) {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setAngleUnits(AngleUnit.rad);
}
},
preferred_numeral_base() {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setPreferredNumeralBase();
}
},
preferred_numeral_base() {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setPreferredNumeralBase();
}
},
preferred_angle_units() {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setPreferredAngleUnits();
}
};
preferred_angle_units() {
@Override
public void fix() {
Locator.getInstance().getPreferenceService().setPreferredAngleUnits();
}
};
@Nonnull
private final List<String> messageCodes;
@Nonnull
private final List<String> messageCodes;
CalculatorFixableError(@Nullable String... messageCodes) {
this.messageCodes = Collections.asList(messageCodes);
}
CalculatorFixableError(@Nullable String... messageCodes) {
this.messageCodes = Collections.asList(messageCodes);
}
@Nullable
public static CalculatorFixableError getErrorByMessageCode(@Nonnull String messageCode) {
for (CalculatorFixableError fixableError : values()) {
if (fixableError.messageCodes.contains(messageCode)) {
return fixableError;
}
}
return null;
}
@Nullable
public static CalculatorFixableError getErrorByMessageCode(@Nonnull String messageCode) {
for (CalculatorFixableError fixableError : values()) {
if (fixableError.messageCodes.contains(messageCode)) {
return fixableError;
}
}
return null;
}
@Nullable
@Override
public CharSequence getFixCaption() {
return null;
}
@Nullable
@Override
public CharSequence getFixCaption() {
return null;
}
}

View File

@@ -22,14 +22,6 @@
package org.solovyev.android.calculator;
import jscl.CustomFunctionCalculationException;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.function.FunctionBuilderAdapter;
import org.solovyev.android.calculator.model.AFunction;
import org.solovyev.android.calculator.model.Functions;
@@ -42,6 +34,14 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.CustomFunctionCalculationException;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
/**
* User: serso
* Date: 11/17/11
@@ -49,103 +49,102 @@ import java.util.Map;
*/
public class CalculatorFunctionsMathRegistry extends AbstractCalculatorMathRegistry<Function, AFunction> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
static {
substitutes.put("", "sqrt");
}
static {
substitutes.put("", "sqrt");
}
@Nonnull
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
public CalculatorFunctionsMathRegistry(@Nonnull MathRegistry<Function> functionsRegistry,
@Nonnull MathEntityDao<AFunction> mathEntityDao) {
super(functionsRegistry, FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
}
public CalculatorFunctionsMathRegistry(@Nonnull MathRegistry<Function> functionsRegistry,
@Nonnull MathEntityDao<AFunction> mathEntityDao) {
super(functionsRegistry, FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
}
public static void saveFunction(@Nonnull CalculatorMathRegistry<Function> registry,
@Nonnull MathEntityBuilder<? extends Function> builder,
@Nullable IFunction editedInstance,
@Nonnull Object source, boolean save) throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
final Function addedFunction = registry.add(builder);
@Override
public void load() {
add(new CustomFunction.Builder(true, "log", Arrays.asList("base", "x"), "ln(x)/ln(base)"));
add(new CustomFunction.Builder(true, "√3", Arrays.asList("x"), "x^(1/3)"));
add(new CustomFunction.Builder(true, "√4", Arrays.asList("x"), "x^(1/4)"));
add(new CustomFunction.Builder(true, "√n", Arrays.asList("x", "n"), "x^(1/n)"));
add(new CustomFunction.Builder(true, "re", Arrays.asList("x"), "(x+conjugate(x))/2"));
add(new CustomFunction.Builder(true, "im", Arrays.asList("x"), "(x-conjugate(x))/(2*i)"));
if (save) {
registry.save();
}
super.load();
}
if (editedInstance == null) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_added, addedFunction, source);
} else {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_changed, ChangeImpl.newInstance(editedInstance, addedFunction), source);
}
}
public static void saveFunction(@Nonnull CalculatorMathRegistry<Function> registry,
@Nonnull MathEntityBuilder<? extends Function> builder,
@Nullable IFunction editedInstance,
@Nonnull Object source, boolean save) throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
final Function addedFunction = registry.add(builder);
@Override
public void load() {
add(new CustomFunction.Builder(true, "log", Arrays.asList("base", "x"), "ln(x)/ln(base)"));
add(new CustomFunction.Builder(true, "√3", Arrays.asList("x"), "x^(1/3)"));
add(new CustomFunction.Builder(true, "√4", Arrays.asList("x"), "x^(1/4)"));
add(new CustomFunction.Builder(true, "√n", Arrays.asList("x", "n"), "x^(1/n)"));
add(new CustomFunction.Builder(true, "re", Arrays.asList("x"), "(x+conjugate(x))/2"));
add(new CustomFunction.Builder(true, "im", Arrays.asList("x"), "(x-conjugate(x))/(2*i)"));
if (save) {
registry.save();
}
super.load();
}
if (editedInstance == null) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_added, addedFunction, source);
} else {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.function_changed, ChangeImpl.newInstance(editedInstance, addedFunction), source);
}
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Override
public String getCategory(@Nonnull Function function) {
for (FunctionCategory category : FunctionCategory.values()) {
if (category.isInCategory(function)) {
return category.name();
}
}
@Override
public String getCategory(@Nonnull Function function) {
for (FunctionCategory category : FunctionCategory.values()) {
if (category.isInCategory(function)) {
return category.name();
}
}
return null;
}
return null;
}
@Nullable
@Override
public String getDescription(@Nonnull String functionName) {
final Function function = get(functionName);
@Nullable
@Override
public String getDescription(@Nonnull String functionName) {
final Function function = get(functionName);
String result = null;
if (function instanceof CustomFunction) {
result = ((CustomFunction) function).getDescription();
}
String result = null;
if (function instanceof CustomFunction) {
result = ((CustomFunction) function).getDescription();
}
if (Strings.isEmpty(result)) {
result = super.getDescription(functionName);
}
if (Strings.isEmpty(result)) {
result = super.getDescription(functionName);
}
return result;
return result;
}
}
@Nonnull
@Override
protected JBuilder<? extends Function> createBuilder(@Nonnull AFunction function) {
return new FunctionBuilderAdapter(new AFunction.Builder(function));
}
@Nonnull
@Override
protected JBuilder<? extends Function> createBuilder(@Nonnull AFunction function) {
return new FunctionBuilderAdapter(new AFunction.Builder(function));
}
@Override
protected AFunction transform(@Nonnull Function function) {
if (function instanceof CustomFunction) {
return AFunction.fromIFunction((CustomFunction) function);
} else {
return null;
}
}
@Override
protected AFunction transform(@Nonnull Function function) {
if (function instanceof CustomFunction) {
return AFunction.fromIFunction((CustomFunction) function);
} else {
return null;
}
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<AFunction> createPersistenceContainer() {
return new Functions();
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<AFunction> createPersistenceContainer() {
return new Functions();
}
}

View File

@@ -22,18 +22,6 @@
package org.solovyev.android.calculator;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation;
@@ -55,6 +43,18 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -63,15 +63,15 @@ import java.util.concurrent.atomic.AtomicLong;
public class CalculatorImpl implements Calculator, CalculatorEventListener {
/*
**********************************************************************
**********************************************************************
*
* CONSTANTS
*
**********************************************************************
*/
// one minute
private static final long PREFERENCE_CHECK_INTERVAL = 1000L * 60L;
// one minute
private static final long PREFERENCE_CHECK_INTERVAL = 1000L * 60L;
/*
**********************************************************************
@@ -81,25 +81,25 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Nonnull
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
@Nonnull
private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer();
@Nonnull
private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID);
@Nonnull
private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID);
@Nonnull
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
@Nonnull
private final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
@Nonnull
private final Executor calculationsExecutor = Executors.newFixedThreadPool(10);
@Nonnull
private final Executor calculationsExecutor = Executors.newFixedThreadPool(10);
// NOTE: only one thread is responsible for events as all events must be done in order of their creating
@Nonnull
private final Executor eventExecutor = Executors.newFixedThreadPool(1);
// NOTE: only one thread is responsible for events as all events must be done in order of their creating
@Nonnull
private final Executor eventExecutor = Executors.newFixedThreadPool(1);
private volatile boolean calculateOnFly = true;
private volatile boolean calculateOnFly = true;
private volatile long lastPreferenceCheck = 0L;
private volatile long lastPreferenceCheck = 0L;
/*
@@ -110,9 +110,9 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
public CalculatorImpl() {
this.addCalculatorEventListener(this);
}
public CalculatorImpl() {
this.addCalculatorEventListener(this);
}
/*
**********************************************************************
@@ -122,23 +122,42 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Nonnull
private CalculatorEventData nextEventData() {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, eventId);
}
@Nonnull
private static String doConversion(@Nonnull Generic generic,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to) throws ConversionException {
final String result;
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Object source) {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
}
if (from != to) {
String fromString = generic.toString();
if (!Strings.isEmpty(fromString)) {
try {
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
} catch (CalculatorParseException e) {
// ok, problems while processing occurred
}
}
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, sequenceId);
}
result = Conversions.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to));
} else {
result = generic.toString();
}
return result;
}
@Nonnull
private CalculatorEventData nextEventData() {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, eventId);
}
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Object source) {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
}
/*
**********************************************************************
@@ -148,213 +167,206 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Override
public void evaluate() {
final CalculatorEditorViewState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId());
}
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, sequenceId);
}
@Override
public void evaluate(@Nonnull Long sequenceId) {
final CalculatorEditorViewState viewState = getEditor().getViewState();
fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId);
this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId);
}
@Override
public void evaluate() {
final CalculatorEditorViewState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId());
}
@Override
public void simplify() {
final CalculatorEditorViewState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId());
}
@Override
public void evaluate(@Nonnull Long sequenceId) {
final CalculatorEditorViewState viewState = getEditor().getViewState();
fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId);
this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId);
}
@Nonnull
@Override
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation,
@Nonnull final String expression) {
@Override
public void simplify() {
final CalculatorEditorViewState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId());
}
final CalculatorEventData eventDataId = nextEventData();
@Nonnull
@Override
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation,
@Nonnull final String expression) {
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
}
});
final CalculatorEventData eventDataId = nextEventData();
return eventDataId;
}
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
}
});
@Nonnull
@Override
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation, @Nonnull final String expression, @Nonnull Long sequenceId) {
final CalculatorEventData eventDataId = nextEventData(sequenceId);
return eventDataId;
}
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
}
});
@Nonnull
@Override
public CalculatorEventData evaluate(@Nonnull final JsclOperation operation, @Nonnull final String expression, @Nonnull Long sequenceId) {
final CalculatorEventData eventDataId = nextEventData(sequenceId);
return eventDataId;
}
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null);
}
});
@Override
public void init() {
Locator.getInstance().getEngine().init();
Locator.getInstance().getHistory().load();
}
return eventDataId;
}
@Override
public void setCalculateOnFly(boolean calculateOnFly) {
if (this.calculateOnFly != calculateOnFly) {
this.calculateOnFly = calculateOnFly;
if (this.calculateOnFly) {
evaluate();
}
}
}
@Override
public void init() {
Locator.getInstance().getEngine().init();
Locator.getInstance().getHistory().load();
}
@Override
public boolean isCalculateOnFly() {
return calculateOnFly;
}
@Override
public boolean isCalculateOnFly() {
return calculateOnFly;
}
@Nonnull
private CalculatorConversionEventData newConversionEventData(@Nonnull Long sequenceId,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull CalculatorDisplayViewState displayViewState) {
return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState);
}
@Override
public void setCalculateOnFly(boolean calculateOnFly) {
if (this.calculateOnFly != calculateOnFly) {
this.calculateOnFly = calculateOnFly;
if (this.calculateOnFly) {
evaluate();
}
}
}
private void evaluate(@Nonnull Long sequenceId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr) {
@Nonnull
private CalculatorConversionEventData newConversionEventData(@Nonnull Long sequenceId,
@Nonnull Generic value,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to,
@Nonnull CalculatorDisplayViewState displayViewState) {
return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState);
}
checkPreferredPreferences();
private void evaluate(@Nonnull Long sequenceId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr) {
PreparedExpression preparedExpression = null;
checkPreferredPreferences();
try {
PreparedExpression preparedExpression = null;
expression = expression.trim();
try {
if (Strings.isEmpty(expression)) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation));
} else {
preparedExpression = prepareExpression(expression);
expression = expression.trim();
final String jsclExpression = preparedExpression.toString();
if (Strings.isEmpty(expression)) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation));
} else {
preparedExpression = prepareExpression(expression);
try {
final String jsclExpression = preparedExpression.toString();
final CalculatorMathEngine mathEngine = Locator.getInstance().getEngine().getMathEngine();
try {
final MessageRegistry messageRegistry = new ListMessageRegistry();
Locator.getInstance().getEngine().getMathEngine0().setMessageRegistry(messageRegistry);
final CalculatorMathEngine mathEngine = Locator.getInstance().getEngine().getMathEngine();
final Generic result = operation.evaluateGeneric(jsclExpression, mathEngine);
final MessageRegistry messageRegistry = new ListMessageRegistry();
Locator.getInstance().getEngine().getMathEngine0().setMessageRegistry(messageRegistry);
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
result.toString();
final Generic result = operation.evaluateGeneric(jsclExpression, mathEngine);
if (messageRegistry.hasMessage()) {
final CalculatorLogger logger = Locator.getInstance().getLogger();
try {
final List<Message> messages = new ArrayList<Message>();
while (messageRegistry.hasMessage()) {
messages.add(messageRegistry.getMessage());
}
if (!messages.isEmpty()) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_messages, messages);
}
} catch (Throwable e) {
// todo serso: not good but we need proper synchronization
logger.error("Calculator", e.getMessage(), e);
}
}
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
result.toString();
final CalculatorOutput data = CalculatorOutputImpl.newOutput(operation.getFromProcessor().process(result), operation, result);
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
if (messageRegistry.hasMessage()) {
final CalculatorLogger logger = Locator.getInstance().getLogger();
try {
final List<Message> messages = new ArrayList<Message>();
while (messageRegistry.hasMessage()) {
messages.add(messageRegistry.getMessage());
}
if (!messages.isEmpty()) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_messages, messages);
}
} catch (Throwable e) {
// todo serso: not good but we need proper synchronization
logger.error("Calculator", e.getMessage(), e);
}
}
} catch (AbstractJsclArithmeticException e) {
handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
}
}
final CalculatorOutput data = CalculatorOutputImpl.newOutput(operation.getFromProcessor().process(result), operation, result);
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data);
} catch (ArithmeticException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
} catch (StackOverflowError e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
} catch (jscl.text.ParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
} catch (ParseInterruptedException e) {
} catch (AbstractJsclArithmeticException e) {
handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression));
}
}
// do nothing - we ourselves interrupt the calculations
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
} catch (ArithmeticException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage())));
} catch (StackOverflowError e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error)));
} catch (jscl.text.ParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, new CalculatorParseException(e));
} catch (ParseInterruptedException e) {
} catch (CalculatorParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
}
}
// do nothing - we ourselves interrupt the calculations
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null);
private void checkPreferredPreferences() {
final long currentTime = System.currentTimeMillis();
} catch (CalculatorParseException e) {
handleException(sequenceId, operation, expression, mr, preparedExpression, e);
}
}
if (currentTime - lastPreferenceCheck > PREFERENCE_CHECK_INTERVAL) {
lastPreferenceCheck = currentTime;
Locator.getInstance().getPreferenceService().checkPreferredPreferences(false);
}
}
private void checkPreferredPreferences() {
final long currentTime = System.currentTimeMillis();
@Nonnull
@Override
public PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException {
return preprocessor.process(expression);
}
if (currentTime - lastPreferenceCheck > PREFERENCE_CHECK_INTERVAL) {
lastPreferenceCheck = currentTime;
Locator.getInstance().getPreferenceService().checkPreferredPreferences(false);
}
}
@Nonnull
private CalculatorEventData newCalculationEventData(@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nonnull Long calculationId) {
return new CalculatorEvaluationEventDataImpl(nextEventData(calculationId), operation, expression);
}
@Nonnull
@Override
public PreparedExpression prepareExpression(@Nonnull String expression) throws CalculatorParseException {
return preprocessor.process(expression);
}
private void handleException(@Nonnull Long sequenceId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr,
@Nullable PreparedExpression preparedExpression,
@Nonnull CalculatorParseException parseException) {
@Nonnull
private CalculatorEventData newCalculationEventData(@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nonnull Long calculationId) {
return new CalculatorEvaluationEventDataImpl(nextEventData(calculationId), operation, expression);
}
if (operation == JsclOperation.numeric
&& preparedExpression != null
&& preparedExpression.isExistsUndefinedVar()) {
private void handleException(@Nonnull Long sequenceId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr,
@Nullable PreparedExpression preparedExpression,
@Nonnull CalculatorParseException parseException) {
evaluate(sequenceId, JsclOperation.simplify, expression, mr);
} else {
if (operation == JsclOperation.numeric
&& preparedExpression != null
&& preparedExpression.isExistsUndefinedVar()) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
}
}
evaluate(sequenceId, JsclOperation.simplify, expression, mr);
} else {
private void handleException(@Nonnull Long calculationId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr,
@Nonnull CalculatorEvalException evalException) {
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
evaluate(calculationId, JsclOperation.simplify, expression, mr);
} else {
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
}
}
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException));
}
}
/*
**********************************************************************
@@ -364,70 +376,58 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Nonnull
@Override
public CalculatorEventData convert(@Nonnull final Generic value,
@Nonnull final NumeralBase to) {
final CalculatorEventData eventDataId = nextEventData();
private void handleException(@Nonnull Long calculationId,
@Nonnull JsclOperation operation,
@Nonnull String expression,
@Nullable MessageRegistry mr,
@Nonnull CalculatorEvalException evalException) {
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
final NumeralBase from = Locator.getInstance().getEngine().getNumeralBase();
if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) {
evaluate(calculationId, JsclOperation.simplify, expression, mr);
} else {
fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException));
}
}
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
final Long sequenceId = eventDataId.getSequenceId();
@Nonnull
@Override
public CalculatorEventData convert(@Nonnull final Generic value,
@Nonnull final NumeralBase to) {
final CalculatorEventData eventDataId = nextEventData();
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null);
try {
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
final NumeralBase from = Locator.getInstance().getEngine().getNumeralBase();
final String result = doConversion(value, from, to);
calculationsExecutor.execute(new Runnable() {
@Override
public void run() {
final Long sequenceId = eventDataId.getSequenceId();
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result);
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null);
try {
} catch (ConversionException e) {
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e));
}
}
});
final String result = doConversion(value, from, to);
return eventDataId;
}
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result);
@Nonnull
private static String doConversion(@Nonnull Generic generic,
@Nonnull NumeralBase from,
@Nonnull NumeralBase to) throws ConversionException {
final String result;
} catch (ConversionException e) {
fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e));
}
}
});
if (from != to) {
String fromString = generic.toString();
if (!Strings.isEmpty(fromString)) {
try {
fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression();
} catch (CalculatorParseException e) {
// ok, problems while processing occurred
}
}
return eventDataId;
}
result = Conversions.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to));
} else {
result = generic.toString();
}
return result;
}
@Override
public boolean isConversionPossible(@Nonnull Generic generic, NumeralBase from, @Nonnull NumeralBase to) {
try {
doConversion(generic, from, to);
return true;
} catch (ConversionException e) {
return false;
}
}
@Override
public boolean isConversionPossible(@Nonnull Generic generic, NumeralBase from, @Nonnull NumeralBase to) {
try {
doConversion(generic, from, to);
return true;
} catch (ConversionException e) {
return false;
}
}
/*
**********************************************************************
@@ -437,65 +437,65 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Override
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
}
@Override
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
calculatorEventContainer.addCalculatorEventListener(calculatorEventListener);
}
@Override
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
}
@Override
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener);
}
@Override
public void fireCalculatorEvent(@Nonnull final CalculatorEventData calculatorEventData, @Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
}
});
}
@Override
public void fireCalculatorEvent(@Nonnull final CalculatorEventData calculatorEventData, @Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
}
});
}
@Override
public void fireCalculatorEvents(@Nonnull final List<CalculatorEvent> calculatorEvents) {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
}
});
}
@Override
public void fireCalculatorEvents(@Nonnull final List<CalculatorEvent> calculatorEvents) {
eventExecutor.execute(new Runnable() {
@Override
public void run() {
calculatorEventContainer.fireCalculatorEvents(calculatorEvents);
}
});
}
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
final CalculatorEventData eventData = nextEventData();
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data) {
final CalculatorEventData eventData = nextEventData();
fireCalculatorEvent(eventData, calculatorEventType, data);
fireCalculatorEvent(eventData, calculatorEventType, data);
return eventData;
}
return eventData;
}
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Object source) {
final CalculatorEventData eventData = nextEventData(source);
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Object source) {
final CalculatorEventData eventData = nextEventData(source);
fireCalculatorEvent(eventData, calculatorEventType, data);
fireCalculatorEvent(eventData, calculatorEventType, data);
return eventData;
}
return eventData;
}
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Long sequenceId) {
final CalculatorEventData eventData = nextEventData(sequenceId);
@Nonnull
@Override
public CalculatorEventData fireCalculatorEvent(@Nonnull final CalculatorEventType calculatorEventType, @Nullable final Object data, @Nonnull Long sequenceId) {
final CalculatorEventData eventData = nextEventData(sequenceId);
fireCalculatorEvent(eventData, calculatorEventType, data);
fireCalculatorEvent(eventData, calculatorEventType, data);
return eventData;
}
return eventData;
}
/*
**********************************************************************
@@ -505,87 +505,87 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) {
case editor_state_changed:
if (calculateOnFly) {
final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data;
switch (calculatorEventType) {
case editor_state_changed:
if (calculateOnFly) {
final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data;
final String newText = editorChangeEventData.getNewValue().getText();
final String oldText = editorChangeEventData.getOldValue().getText();
final String newText = editorChangeEventData.getNewValue().getText();
final String oldText = editorChangeEventData.getOldValue().getText();
if (!newText.equals(oldText)) {
evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getText(), calculatorEventData.getSequenceId());
}
}
break;
if (!newText.equals(oldText)) {
evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getText(), calculatorEventData.getSequenceId());
}
}
break;
case display_state_changed:
onDisplayStateChanged((CalculatorDisplayChangeEventData) data);
break;
case display_state_changed:
onDisplayStateChanged((CalculatorDisplayChangeEventData) data);
break;
case constant_changed:
final IConstant newConstant = ((Change<IConstant>) data).getNewValue();
if (!newConstant.getName().equals(CalculatorVarsRegistry.ANS)) {
evaluate();
}
break;
case constant_changed:
final IConstant newConstant = ((Change<IConstant>) data).getNewValue();
if (!newConstant.getName().equals(CalculatorVarsRegistry.ANS)) {
evaluate();
}
break;
case constant_added:
case constant_removed:
case function_added:
case function_changed:
case function_removed:
evaluate();
break;
case constant_added:
case constant_removed:
case function_added:
case function_changed:
case function_removed:
evaluate();
break;
case engine_preferences_changed:
evaluate(calculatorEventData.getSequenceId());
break;
case engine_preferences_changed:
evaluate(calculatorEventData.getSequenceId());
break;
case use_constant:
final IConstant constant = (IConstant) data;
Locator.getInstance().getKeyboard().buttonPressed(constant.getName());
break;
case use_constant:
final IConstant constant = (IConstant) data;
Locator.getInstance().getKeyboard().buttonPressed(constant.getName());
break;
case use_operator:
final Operator operator = (Operator) data;
Locator.getInstance().getKeyboard().buttonPressed(operator.getName());
break;
case use_operator:
final Operator operator = (Operator) data;
Locator.getInstance().getKeyboard().buttonPressed(operator.getName());
break;
case use_function:
final Function function = (Function) data;
Locator.getInstance().getKeyboard().buttonPressed(function.getName());
break;
case use_function:
final Function function = (Function) data;
Locator.getInstance().getKeyboard().buttonPressed(function.getName());
break;
}
}
}
}
private void onDisplayStateChanged(@Nonnull CalculatorDisplayChangeEventData displayChangeEventData) {
final CalculatorDisplayViewState newState = displayChangeEventData.getNewValue();
if (newState.isValid()) {
final String result = newState.getStringResult();
if (!Strings.isEmpty(result)) {
final CalculatorMathRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVarsRegistry();
final IConstant ansVar = varsRegistry.get(CalculatorVarsRegistry.ANS);
private void onDisplayStateChanged(@Nonnull CalculatorDisplayChangeEventData displayChangeEventData) {
final CalculatorDisplayViewState newState = displayChangeEventData.getNewValue();
if (newState.isValid()) {
final String result = newState.getStringResult();
if (!Strings.isEmpty(result)) {
final CalculatorMathRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVarsRegistry();
final IConstant ansVar = varsRegistry.get(CalculatorVarsRegistry.ANS);
final Var.Builder varBuilder;
if (ansVar != null) {
varBuilder = new Var.Builder(ansVar);
} else {
varBuilder = new Var.Builder();
}
final Var.Builder varBuilder;
if (ansVar != null) {
varBuilder = new Var.Builder(ansVar);
} else {
varBuilder = new Var.Builder();
}
varBuilder.setName(CalculatorVarsRegistry.ANS);
varBuilder.setValue(result);
varBuilder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
varBuilder.setName(CalculatorVarsRegistry.ANS);
varBuilder.setValue(result);
varBuilder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
CalculatorVarsRegistry.saveVariable(varsRegistry, varBuilder, ansVar, this, false);
}
}
}
CalculatorVarsRegistry.saveVariable(varsRegistry, varBuilder, ansVar, this, false);
}
}
}
/*
**********************************************************************
@@ -595,27 +595,27 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Override
public void doHistoryAction(@Nonnull HistoryAction historyAction) {
final CalculatorHistory history = Locator.getInstance().getHistory();
if (history.isActionAvailable(historyAction)) {
final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState());
if (newState != null) {
setCurrentHistoryState(newState);
}
}
}
@Override
public void doHistoryAction(@Nonnull HistoryAction historyAction) {
final CalculatorHistory history = Locator.getInstance().getHistory();
if (history.isActionAvailable(historyAction)) {
final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState());
if (newState != null) {
setCurrentHistoryState(newState);
}
}
}
@Override
public void setCurrentHistoryState(@Nonnull CalculatorHistoryState editorHistoryState) {
editorHistoryState.setValuesFromHistory(getEditor(), getDisplay());
}
@Nonnull
@Override
public CalculatorHistoryState getCurrentHistoryState() {
return CalculatorHistoryState.newInstance(getEditor(), getDisplay());
}
@Nonnull
@Override
public CalculatorHistoryState getCurrentHistoryState() {
return CalculatorHistoryState.newInstance(getEditor(), getDisplay());
}
@Override
public void setCurrentHistoryState(@Nonnull CalculatorHistoryState editorHistoryState) {
editorHistoryState.setValuesFromHistory(getEditor(), getDisplay());
}
/*
**********************************************************************
@@ -625,13 +625,13 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
**********************************************************************
*/
@Nonnull
private CalculatorEditor getEditor() {
return Locator.getInstance().getEditor();
}
@Nonnull
private CalculatorEditor getEditor() {
return Locator.getInstance().getEditor();
}
@Nonnull
private CalculatorDisplay getDisplay() {
return Locator.getInstance().getDisplay();
}
@Nonnull
private CalculatorDisplay getDisplay() {
return Locator.getInstance().getDisplay();
}
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/20/12
@@ -33,9 +33,9 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public interface CalculatorInput {
@Nonnull
String getExpression();
@Nonnull
String getExpression();
@Nonnull
JsclOperation getOperation();
@Nonnull
JsclOperation getOperation();
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/20/12
@@ -33,26 +33,26 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public class CalculatorInputImpl implements CalculatorInput {
@Nonnull
private String expression;
@Nonnull
private String expression;
@Nonnull
private JsclOperation operation;
@Nonnull
private JsclOperation operation;
public CalculatorInputImpl(@Nonnull String expression, @Nonnull JsclOperation operation) {
this.expression = expression;
this.operation = operation;
}
public CalculatorInputImpl(@Nonnull String expression, @Nonnull JsclOperation operation) {
this.expression = expression;
this.operation = operation;
}
@Override
@Nonnull
public String getExpression() {
return expression;
}
@Override
@Nonnull
public String getExpression() {
return expression;
}
@Override
@Nonnull
public JsclOperation getOperation() {
return operation;
}
@Override
@Nonnull
public JsclOperation getOperation() {
return operation;
}
}

View File

@@ -31,17 +31,17 @@ import javax.annotation.Nullable;
*/
public interface CalculatorKeyboard {
boolean buttonPressed(@Nullable String text);
boolean buttonPressed(@Nullable String text);
void roundBracketsButtonPressed();
void roundBracketsButtonPressed();
void pasteButtonPressed();
void pasteButtonPressed();
void clearButtonPressed();
void clearButtonPressed();
void copyButtonPressed();
void copyButtonPressed();
void moveCursorLeft();
void moveCursorLeft();
void moveCursorRight();
void moveCursorRight();
}

View File

@@ -35,127 +35,127 @@ import javax.annotation.Nullable;
*/
public class CalculatorKeyboardImpl implements CalculatorKeyboard {
@Nonnull
private final Calculator calculator;
@Nonnull
private final Calculator calculator;
public CalculatorKeyboardImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
}
public CalculatorKeyboardImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
}
@Override
public boolean buttonPressed(@Nullable final String text) {
if (!Strings.isEmpty(text)) {
if (text == null) throw new AssertionError();
@Override
public boolean buttonPressed(@Nullable final String text) {
if (!Strings.isEmpty(text)) {
if (text == null) throw new AssertionError();
// process special buttons
boolean processed = processSpecialButtons(text);
// process special buttons
boolean processed = processSpecialButtons(text);
if (!processed) {
processText(prepareText(text));
}
return true;
}
return false;
}
if (!processed) {
processText(prepareText(text));
}
return true;
}
return false;
}
private void processText(@Nonnull String text) {
int cursorPositionOffset = 0;
final StringBuilder textToBeInserted = new StringBuilder(text);
private void processText(@Nonnull String text) {
int cursorPositionOffset = 0;
final StringBuilder textToBeInserted = new StringBuilder(text);
final MathType.Result mathType = MathType.getType(text, 0, false);
switch (mathType.getMathType()) {
case function:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
case operator:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
case comma:
textToBeInserted.append(" ");
break;
}
final MathType.Result mathType = MathType.getType(text, 0, false);
switch (mathType.getMathType()) {
case function:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
case operator:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
case comma:
textToBeInserted.append(" ");
break;
}
if (cursorPositionOffset == 0) {
if (MathType.openGroupSymbols.contains(text)) {
cursorPositionOffset = -1;
}
}
if (cursorPositionOffset == 0) {
if (MathType.openGroupSymbols.contains(text)) {
cursorPositionOffset = -1;
}
}
final CalculatorEditor editor = Locator.getInstance().getEditor();
editor.insert(textToBeInserted.toString(), cursorPositionOffset);
}
final CalculatorEditor editor = Locator.getInstance().getEditor();
editor.insert(textToBeInserted.toString(), cursorPositionOffset);
}
@Nonnull
private String prepareText(@Nonnull String text) {
if ("( )".equals(text) || "( )".equals(text)) {
return "()";
} else {
return text;
}
}
@Nonnull
private String prepareText(@Nonnull String text) {
if ("( )".equals(text) || "( )".equals(text)) {
return "()";
} else {
return text;
}
}
private boolean processSpecialButtons(@Nonnull String text) {
boolean result = false;
private boolean processSpecialButtons(@Nonnull String text) {
boolean result = false;
final CalculatorSpecialButton button = CalculatorSpecialButton.getByActionCode(text);
if (button != null) {
button.onClick(this);
result = true;
}
final CalculatorSpecialButton button = CalculatorSpecialButton.getByActionCode(text);
if (button != null) {
button.onClick(this);
result = true;
}
return result;
}
return result;
}
@Override
public void roundBracketsButtonPressed() {
final CalculatorEditor editor = Locator.getInstance().getEditor();
CalculatorEditorViewState viewState = editor.getViewState();
@Override
public void roundBracketsButtonPressed() {
final CalculatorEditor editor = Locator.getInstance().getEditor();
CalculatorEditorViewState viewState = editor.getViewState();
final int cursorPosition = viewState.getSelection();
final String oldText = viewState.getText();
final int cursorPosition = viewState.getSelection();
final String oldText = viewState.getText();
final StringBuilder newText = new StringBuilder(oldText.length() + 2);
newText.append("(");
newText.append(oldText.substring(0, cursorPosition));
newText.append(")");
newText.append(oldText.substring(cursorPosition));
editor.setText(newText.toString(), cursorPosition + 2);
}
final StringBuilder newText = new StringBuilder(oldText.length() + 2);
newText.append("(");
newText.append(oldText.substring(0, cursorPosition));
newText.append(")");
newText.append(oldText.substring(cursorPosition));
editor.setText(newText.toString(), cursorPosition + 2);
}
@Override
public void pasteButtonPressed() {
final String text = Locator.getInstance().getClipboard().getText();
if (text != null) {
Locator.getInstance().getEditor().insert(text);
}
}
@Override
public void pasteButtonPressed() {
final String text = Locator.getInstance().getClipboard().getText();
if (text != null) {
Locator.getInstance().getEditor().insert(text);
}
}
@Override
public void clearButtonPressed() {
Locator.getInstance().getEditor().clear();
}
@Override
public void clearButtonPressed() {
Locator.getInstance().getEditor().clear();
}
@Override
public void copyButtonPressed() {
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
if (displayViewState.isValid()) {
final CharSequence text = displayViewState.getText();
if (!Strings.isEmpty(text)) {
Locator.getInstance().getClipboard().setText(text);
Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
}
}
}
@Override
public void copyButtonPressed() {
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
if (displayViewState.isValid()) {
final CharSequence text = displayViewState.getText();
if (!Strings.isEmpty(text)) {
Locator.getInstance().getClipboard().setText(text);
Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
}
}
}
@Override
public void moveCursorLeft() {
Locator.getInstance().getEditor().moveCursorLeft();
}
@Override
public void moveCursorLeft() {
Locator.getInstance().getEditor().moveCursorLeft();
}
@Override
public void moveCursorRight() {
Locator.getInstance().getEditor().moveCursorRight();
}
@Override
public void moveCursorRight() {
Locator.getInstance().getEditor().moveCursorRight();
}
}

View File

@@ -37,47 +37,47 @@ import javax.annotation.Nullable;
*/
public interface CalculatorLocator {
void init(@Nonnull Calculator calculator,
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull CalculatorHistory history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor);
void init(@Nonnull Calculator calculator,
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull CalculatorHistory history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor);
@Nonnull
Calculator getCalculator();
@Nonnull
Calculator getCalculator();
@Nonnull
CalculatorEngine getEngine();
@Nonnull
CalculatorEngine getEngine();
@Nonnull
CalculatorDisplay getDisplay();
@Nonnull
CalculatorDisplay getDisplay();
@Nonnull
CalculatorEditor getEditor();
@Nonnull
CalculatorEditor getEditor();
@Nonnull
CalculatorKeyboard getKeyboard();
@Nonnull
CalculatorKeyboard getKeyboard();
@Nonnull
CalculatorClipboard getClipboard();
@Nonnull
CalculatorClipboard getClipboard();
@Nonnull
CalculatorNotifier getNotifier();
@Nonnull
CalculatorNotifier getNotifier();
@Nonnull
CalculatorHistory getHistory();
@Nonnull
CalculatorHistory getHistory();
@Nonnull
CalculatorLogger getLogger();
@Nonnull
CalculatorLogger getLogger();
@Nonnull
CalculatorPlotter getPlotter();
@Nonnull
CalculatorPlotter getPlotter();
@Nonnull
CalculatorPreferenceService getPreferenceService();
@Nonnull
CalculatorPreferenceService getPreferenceService();
}

View File

@@ -32,12 +32,12 @@ import javax.annotation.Nullable;
*/
public interface CalculatorLogger {
void debug(@Nullable String tag, @Nonnull String message);
void debug(@Nullable String tag, @Nonnull String message);
void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e);
void error(@Nullable String tag, @Nullable String message);
void error(@Nullable String tag, @Nullable String message);
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import jscl.math.Generic;
import jscl.text.ParseException;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/23/12
@@ -34,21 +34,21 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorMathEngine {
@Nonnull
String evaluate(@Nonnull String expression) throws ParseException;
@Nonnull
String evaluate(@Nonnull String expression) throws ParseException;
@Nonnull
String simplify(@Nonnull String expression) throws ParseException;
@Nonnull
String simplify(@Nonnull String expression) throws ParseException;
@Nonnull
String elementary(@Nonnull String expression) throws ParseException;
@Nonnull
String elementary(@Nonnull String expression) throws ParseException;
@Nonnull
Generic evaluateGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic evaluateGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic simplifyGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic simplifyGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic elementaryGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic elementaryGeneric(@Nonnull String expression) throws ParseException;
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/30/11
@@ -35,13 +35,13 @@ import org.solovyev.common.math.MathRegistry;
*/
public interface CalculatorMathRegistry<T extends MathEntity> extends MathRegistry<T> {
@Nullable
String getDescription(@Nonnull String mathEntityName);
@Nullable
String getDescription(@Nonnull String mathEntityName);
@Nullable
String getCategory(@Nonnull T mathEntity);
@Nullable
String getCategory(@Nonnull T mathEntity);
void load();
void load();
void save();
void save();
}

View File

@@ -22,9 +22,6 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.AbstractMessage;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
@@ -33,6 +30,9 @@ import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 9/20/12
@@ -40,32 +40,32 @@ import java.util.ResourceBundle;
*/
public class CalculatorMessage extends AbstractMessage {
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
super(messageCode, messageType, parameters);
}
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
super(messageCode, messageType, parameters);
}
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nonnull List<?> parameters) {
super(messageCode, messageType, parameters);
}
public CalculatorMessage(@Nonnull String messageCode, @Nonnull MessageType messageType, @Nonnull List<?> parameters) {
super(messageCode, messageType, parameters);
}
@Nonnull
public static Message newInfoMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.info, parameters);
}
@Nonnull
public static Message newInfoMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.info, parameters);
}
@Nonnull
public static Message newWarningMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.warning, parameters);
}
@Nonnull
public static Message newWarningMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.warning, parameters);
}
@Nonnull
public static Message newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.error, parameters);
}
@Nonnull
public static Message newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, MessageType.error, parameters);
}
@Override
protected String getMessagePattern(@Nonnull Locale locale) {
final ResourceBundle rb = CalculatorMessages.getBundle(locale);
return rb.getString(getMessageCode());
}
@Override
protected String getMessagePattern(@Nonnull Locale locale) {
final ResourceBundle rb = CalculatorMessages.getBundle(locale);
return rb.getString(getMessageCode());
}
}

View File

@@ -24,13 +24,13 @@ package org.solovyev.android.calculator;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.solovyev.common.msg.MessageType.error;
import static org.solovyev.common.msg.MessageType.info;
import static org.solovyev.common.msg.MessageType.warning;
@@ -43,72 +43,62 @@ import static org.solovyev.common.msg.MessageType.warning;
public final class CalculatorMessages {
private CalculatorMessages() {
throw new AssertionError();
}
/* Arithmetic error occurred: {0} */
public static final String msg_001 = "msg_1";
/* Too complex expression*/
public static final String msg_002 = "msg_2";
/* Too long execution time - check the expression*/
public static final String msg_003 = "msg_3";
/* Evaluation was cancelled*/
public static final String msg_004 = "msg_4";
/* No parameters are specified for function: {0}*/
public static final String msg_005 = "msg_5";
/* Infinite loop is detected in expression*/
public static final String msg_006 = "msg_6";
/**
* Some data could not be loaded. Contact authors of application with information below.\n\nUnable to load:\n{0}
*/
public static final String msg_007 = "msg_7";
/* Error */
public static final String syntax_error = "syntax_error";
/* Result copied to clipboard! */
public static final String result_copied = "result_copied";
/* Text copied to clipboard! */
public static final String text_copied = "text_copied";
/* Last calculated value */
public static final String ans_description = "ans_description";
@Nonnull
public static ResourceBundle getBundle() {
return getBundle(Locale.getDefault());
}
private CalculatorMessages() {
throw new AssertionError();
}
@Nonnull
public static ResourceBundle getBundle(@Nonnull Locale locale) {
try {
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", locale);
} catch (MissingResourceException e) {
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", Locale.ENGLISH);
}
}
@Nonnull
public static ResourceBundle getBundle() {
return getBundle(Locale.getDefault());
}
/* Arithmetic error occurred: {0} */
public static final String msg_001 = "msg_1";
@Nonnull
public static ResourceBundle getBundle(@Nonnull Locale locale) {
try {
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", locale);
} catch (MissingResourceException e) {
return ResourceBundle.getBundle("org/solovyev/android/calculator/messages", Locale.ENGLISH);
}
}
/* Too complex expression*/
public static final String msg_002 = "msg_2";
@Nonnull
public static CalculatorMessage newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, error, parameters);
}
/* Too long execution time - check the expression*/
public static final String msg_003 = "msg_3";
@Nonnull
static MessageType toMessageType(int messageLevel) {
if (messageLevel < info.getMessageLevel()) {
return info;
} else if (messageLevel < warning.getMessageLevel()) {
return warning;
}
/* Evaluation was cancelled*/
public static final String msg_004 = "msg_4";
/* No parameters are specified for function: {0}*/
public static final String msg_005 = "msg_5";
/* Infinite loop is detected in expression*/
public static final String msg_006 = "msg_6";
/**
* Some data could not be loaded. Contact authors of application with information below.\n\nUnable to load:\n{0}
*/
public static final String msg_007 = "msg_7";
/* Error */
public static final String syntax_error = "syntax_error";
/* Result copied to clipboard! */
public static final String result_copied = "result_copied";
/* Text copied to clipboard! */
public static final String text_copied = "text_copied";
/* Last calculated value */
public static final String ans_description = "ans_description";
@Nonnull
public static CalculatorMessage newErrorMessage(@Nonnull String messageCode, @Nullable Object... parameters) {
return new CalculatorMessage(messageCode, error, parameters);
}
@Nonnull
static MessageType toMessageType(int messageLevel) {
if (messageLevel < info.getMessageLevel()) {
return info;
} else if (messageLevel < warning.getMessageLevel()) {
return warning;
}
return error;
}
return error;
}
}

View File

@@ -22,14 +22,14 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 9/22/12
@@ -37,11 +37,11 @@ import java.util.List;
*/
public interface CalculatorNotifier {
void showMessage(@Nonnull Message message);
void showMessage(@Nonnull Message message);
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters);
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters);
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters);
void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters);
void showDebugMessage(@Nullable String tag, @Nonnull String message);
void showDebugMessage(@Nullable String tag, @Nonnull String message);
}

View File

@@ -22,16 +22,16 @@
package org.solovyev.android.calculator;
import jscl.math.operator.Operator;
import javax.annotation.Nonnull;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathRegistry;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import jscl.math.operator.Operator;
/**
* User: serso
* Date: 11/17/11
@@ -39,71 +39,70 @@ import java.util.Map;
*/
public class CalculatorOperatorsMathRegistry extends AbstractCalculatorMathRegistry<Operator, MathPersistenceEntity> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final String OPERATOR_DESCRIPTION_PREFIX = "c_op_description_";
static {
substitutes.put("Σ", "sum");
substitutes.put("", "product");
substitutes.put("", "derivative");
substitutes.put("∫ab", "integral_ab");
substitutes.put("", "integral");
substitutes.put("Σ", "sum");
}
static {
substitutes.put("Σ", "sum");
substitutes.put("", "product");
substitutes.put("", "derivative");
substitutes.put("∫ab", "integral_ab");
substitutes.put("", "integral");
substitutes.put("Σ", "sum");
}
@Nonnull
private static final String OPERATOR_DESCRIPTION_PREFIX = "c_op_description_";
public CalculatorOperatorsMathRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
super(functionsRegistry, OPERATOR_DESCRIPTION_PREFIX, mathEntityDao);
}
public CalculatorOperatorsMathRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
super(functionsRegistry, OPERATOR_DESCRIPTION_PREFIX, mathEntityDao);
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Override
public String getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category.name();
}
}
return null;
}
@Override
public String getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category.name();
}
}
return null;
}
@Override
public void load() {
// not supported yet
}
@Override
public void load() {
// not supported yet
}
@Nonnull
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nonnull
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void save() {
// not supported yet
}
@Override
public void save() {
// not supported yet
}
@Override
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
/*
**********************************************************************
**********************************************************************
*
* STATIC
*

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator;
import jscl.math.Generic;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import jscl.math.Generic;
/**
* User: serso
@@ -36,14 +36,14 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public interface CalculatorOutput {
@Nonnull
String getStringResult();
@Nonnull
String getStringResult();
@Nonnull
JsclOperation getOperation();
@Nonnull
JsclOperation getOperation();
// null in case of empty expression
@Nullable
Generic getResult();
// null in case of empty expression
@Nullable
Generic getResult();
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator;
import jscl.math.Generic;
import org.solovyev.android.calculator.jscl.JsclOperation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
import jscl.math.Generic;
/**
* User: serso
@@ -36,50 +36,50 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/
public class CalculatorOutputImpl implements CalculatorOutput {
@Nullable
private Generic result;
@Nullable
private Generic result;
@Nonnull
private String stringResult;
@Nonnull
private String stringResult;
@Nonnull
private JsclOperation operation;
@Nonnull
private JsclOperation operation;
private CalculatorOutputImpl(@Nonnull String stringResult,
@Nonnull JsclOperation operation,
@Nullable Generic result) {
this.stringResult = stringResult;
this.operation = operation;
this.result = result;
}
private CalculatorOutputImpl(@Nonnull String stringResult,
@Nonnull JsclOperation operation,
@Nullable Generic result) {
this.stringResult = stringResult;
this.operation = operation;
this.result = result;
}
@Nonnull
public static CalculatorOutput newOutput(@Nonnull String stringResult,
@Nonnull JsclOperation operation,
@Nonnull Generic result) {
return new CalculatorOutputImpl(stringResult, operation, result);
}
@Nonnull
public static CalculatorOutput newOutput(@Nonnull String stringResult,
@Nonnull JsclOperation operation,
@Nonnull Generic result) {
return new CalculatorOutputImpl(stringResult, operation, result);
}
@Nonnull
public static CalculatorOutput newEmptyOutput(@Nonnull JsclOperation operation) {
return new CalculatorOutputImpl("", operation, null);
}
@Nonnull
public static CalculatorOutput newEmptyOutput(@Nonnull JsclOperation operation) {
return new CalculatorOutputImpl("", operation, null);
}
@Override
@Nonnull
public String getStringResult() {
return stringResult;
}
@Override
@Nonnull
public String getStringResult() {
return stringResult;
}
@Override
@Nonnull
public JsclOperation getOperation() {
return operation;
}
@Override
@Nonnull
public JsclOperation getOperation() {
return operation;
}
@Override
@Nullable
public Generic getResult() {
return result;
}
@Override
@Nullable
public Generic getResult() {
return result;
}
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageLevel;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/6/11
@@ -38,71 +38,71 @@ import java.util.Locale;
*/
public class CalculatorParseException extends Exception implements Message {
@Nonnull
private final Message message;
@Nonnull
private final Message message;
@Nonnull
private final String expression;
@Nonnull
private final String expression;
@Nullable
private final Integer position;
@Nullable
private final Integer position;
public CalculatorParseException(@Nonnull jscl.text.ParseException jsclParseException) {
this.message = jsclParseException;
this.expression = jsclParseException.getExpression();
this.position = jsclParseException.getPosition();
}
public CalculatorParseException(@Nonnull jscl.text.ParseException jsclParseException) {
this.message = jsclParseException;
this.expression = jsclParseException.getExpression();
this.position = jsclParseException.getPosition();
}
public CalculatorParseException(@Nullable Integer position,
@Nonnull String expression,
@Nonnull Message message) {
this.message = message;
this.expression = expression;
this.position = position;
}
public CalculatorParseException(@Nullable Integer position,
@Nonnull String expression,
@Nonnull Message message) {
this.message = message;
this.expression = expression;
this.position = position;
}
public CalculatorParseException(@Nonnull String expression,
@Nonnull Message message) {
this(null, expression, message);
}
public CalculatorParseException(@Nonnull String expression,
@Nonnull Message message) {
this(null, expression, message);
}
@Nonnull
public String getExpression() {
return expression;
}
@Nonnull
public String getExpression() {
return expression;
}
@Nullable
public Integer getPosition() {
return position;
}
@Nullable
public Integer getPosition() {
return position;
}
@Nonnull
@Override
public String getMessageCode() {
return this.message.getMessageCode();
}
@Nonnull
@Override
public String getMessageCode() {
return this.message.getMessageCode();
}
@Nonnull
@Override
public List<Object> getParameters() {
return this.message.getParameters();
}
@Nonnull
@Override
public List<Object> getParameters() {
return this.message.getParameters();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return this.message.getMessageLevel();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return this.message.getMessageLevel();
}
@Override
@Nonnull
public String getLocalizedMessage() {
return this.message.getLocalizedMessage(Locale.getDefault());
}
@Override
@Nonnull
public String getLocalizedMessage() {
return this.message.getLocalizedMessage(Locale.getDefault());
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale);
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale);
}
}

View File

@@ -22,14 +22,16 @@
package org.solovyev.android.calculator;
import jscl.math.operator.Operator;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathRegistry;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import jscl.math.operator.Operator;
/**
* User: serso
* Date: 11/19/11
@@ -37,65 +39,64 @@ import java.util.Map;
*/
public class CalculatorPostfixFunctionsRegistry extends AbstractCalculatorMathRegistry<Operator, MathPersistenceEntity> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final String POSTFIX_FUNCTION_DESCRIPTION_PREFIX = "c_pf_description_";
static {
substitutes.put("%", "percent");
substitutes.put("!", "factorial");
substitutes.put("!!", "double_factorial");
substitutes.put("°", "degree");
}
static {
substitutes.put("%", "percent");
substitutes.put("!", "factorial");
substitutes.put("!!", "double_factorial");
substitutes.put("°", "degree");
}
@Nonnull
private static final String POSTFIX_FUNCTION_DESCRIPTION_PREFIX = "c_pf_description_";
public CalculatorPostfixFunctionsRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
super(functionsRegistry, POSTFIX_FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
}
public CalculatorPostfixFunctionsRegistry(@Nonnull MathRegistry<Operator> functionsRegistry,
@Nonnull MathEntityDao<MathPersistenceEntity> mathEntityDao) {
super(functionsRegistry, POSTFIX_FUNCTION_DESCRIPTION_PREFIX, mathEntityDao);
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Override
public String getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category.name();
}
}
return null;
}
@Override
public String getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category.name();
}
}
return null;
}
@Override
public void load() {
// not supported yet
}
@Override
public void load() {
// not supported yet
}
@Nonnull
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
throw new UnsupportedOperationException();
}
@Override
public void save() {
// not supported yet
}
@Override
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
return null;
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
@Nonnull
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull MathPersistenceEntity entity) {
throw new UnsupportedOperationException();
}
}
@Override
public void save() {
// not supported yet
}
@Override
protected MathPersistenceEntity transform(@Nonnull Operator entity) {
return null;
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<MathPersistenceEntity> createPersistenceContainer() {
throw new UnsupportedOperationException();
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import jscl.AngleUnit;
import jscl.NumeralBase;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 11/17/12
@@ -34,13 +34,13 @@ import javax.annotation.Nonnull;
*/
public interface CalculatorPreferenceService {
void setPreferredAngleUnits();
void setPreferredAngleUnits();
void setAngleUnits(@Nonnull AngleUnit angleUnit);
void setAngleUnits(@Nonnull AngleUnit angleUnit);
void setPreferredNumeralBase();
void setPreferredNumeralBase();
void setNumeralBase(@Nonnull NumeralBase numeralBase);
void setNumeralBase(@Nonnull NumeralBase numeralBase);
void checkPreferredPreferences(boolean force);
void checkPreferredPreferences(boolean force);
}

View File

@@ -24,12 +24,12 @@ package org.solovyev.android.calculator;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/20/12
@@ -37,172 +37,172 @@ import java.util.Map;
*/
public enum CalculatorSpecialButton {
history("history") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history, null);
}
},
history_detached("history_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history_detached, null);
}
},
cursor_right("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.moveCursorRight();
}
},
cursor_left("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.moveCursorLeft();
}
},
settings("settings") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings, null);
}
},
history("history") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history, null);
}
},
history_detached("history_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history_detached, null);
}
},
cursor_right("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.moveCursorRight();
}
},
cursor_left("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.moveCursorLeft();
}
},
settings("settings") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings, null);
}
},
settings_detached("settings_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings_detached, null);
}
},
settings_detached("settings_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings_detached, null);
}
},
like("like") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_like_dialog, null);
}
},
erase("erase") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getEditor().erase();
}
},
paste("paste") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.pasteButtonPressed();
}
},
copy("copy") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.copyButtonPressed();
}
},
equals("=") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
final Calculator calculator = Locator.getInstance().getCalculator();
if (!calculator.isCalculateOnFly()) {
// no automatic calculations are => equals button must be used to calculate
calculator.evaluate();
return;
}
like("like") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_like_dialog, null);
}
},
erase("erase") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getEditor().erase();
}
},
paste("paste") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.pasteButtonPressed();
}
},
copy("copy") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.copyButtonPressed();
}
},
equals("=") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
final Calculator calculator = Locator.getInstance().getCalculator();
if (!calculator.isCalculateOnFly()) {
// no automatic calculations are => equals button must be used to calculate
calculator.evaluate();
return;
}
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
if (displayViewState.isValid()) {
final CharSequence text = displayViewState.getText();
if (!Strings.isEmpty(text)) {
Locator.getInstance().getEditor().setText(text.toString());
}
}
}
},
clear("clear") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.clearButtonPressed();
}
},
functions("functions") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions, null);
}
},
functions_detached("functions_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions_detached, null);
}
},
open_app("open_app") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.open_app, null);
}
},
vars("vars") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars, null);
}
},
vars_detached("vars_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars_detached, null);
}
},
operators("operators") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators, null);
}
},
final CalculatorDisplayViewState displayViewState = Locator.getInstance().getDisplay().getViewState();
if (displayViewState.isValid()) {
final CharSequence text = displayViewState.getText();
if (!Strings.isEmpty(text)) {
Locator.getInstance().getEditor().setText(text.toString());
}
}
}
},
clear("clear") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
keyboard.clearButtonPressed();
}
},
functions("functions") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions, null);
}
},
functions_detached("functions_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions_detached, null);
}
},
open_app("open_app") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.open_app, null);
}
},
vars("vars") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars, null);
}
},
vars_detached("vars_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars_detached, null);
}
},
operators("operators") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators, null);
}
},
operators_detached("operators_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators_detached, null);
}
};
operators_detached("operators_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators_detached, null);
}
};
@Nonnull
private static Map<String, CalculatorSpecialButton> buttonsByActionCodes = new HashMap<>();
@Nonnull
private static Map<String, CalculatorSpecialButton> buttonsByActionCodes = new HashMap<>();
@Nonnull
private final String actionCode;
@Nonnull
private final String actionCode;
CalculatorSpecialButton(@Nonnull String actionCode) {
this.actionCode = actionCode;
}
CalculatorSpecialButton(@Nonnull String actionCode) {
this.actionCode = actionCode;
}
@Nonnull
public String getActionCode() {
return actionCode;
}
@Nullable
public static CalculatorSpecialButton getByActionCode(@Nonnull String actionCode) {
initButtonsByActionCodesMap();
return buttonsByActionCodes.get(actionCode);
}
@Nullable
public static CalculatorSpecialButton getByActionCode(@Nonnull String actionCode) {
initButtonsByActionCodesMap();
return buttonsByActionCodes.get(actionCode);
}
private static void initButtonsByActionCodesMap() {
if (buttonsByActionCodes.isEmpty()) {
// if not initialized
public abstract void onClick(@Nonnull CalculatorKeyboard keyboard);
final CalculatorSpecialButton[] specialButtons = values();
private static void initButtonsByActionCodesMap() {
if (buttonsByActionCodes.isEmpty()) {
// if not initialized
final Map<String, CalculatorSpecialButton> localButtonsByActionCodes = new HashMap<String, CalculatorSpecialButton>(specialButtons.length);
for (CalculatorSpecialButton specialButton : specialButtons) {
localButtonsByActionCodes.put(specialButton.getActionCode(), specialButton);
}
final CalculatorSpecialButton[] specialButtons = values();
buttonsByActionCodes = localButtonsByActionCodes;
}
}
final Map<String, CalculatorSpecialButton> localButtonsByActionCodes = new HashMap<String, CalculatorSpecialButton>(specialButtons.length);
for (CalculatorSpecialButton specialButton : specialButtons) {
localButtonsByActionCodes.put(specialButton.getActionCode(), specialButton);
}
@Nonnull
public String getActionCode() {
return actionCode;
}
buttonsByActionCodes = localButtonsByActionCodes;
}
}
public abstract void onClick(@Nonnull CalculatorKeyboard keyboard);
}

View File

@@ -22,14 +22,14 @@
package org.solovyev.android.calculator;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.math.function.IConstant;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.math.function.IConstant;
/**
* User: serso
@@ -38,29 +38,29 @@ import java.util.Set;
*/
public final class CalculatorUtils {
static final long FIRST_ID = 0;
static final long FIRST_ID = 0;
private CalculatorUtils() {
throw new AssertionError();
}
private CalculatorUtils() {
throw new AssertionError();
}
@Nonnull
public static CalculatorEventData createFirstEventDataId() {
return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID);
}
@Nonnull
public static CalculatorEventData createFirstEventDataId() {
return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID);
}
@Nonnull
public static Set<Constant> getNotSystemConstants(@Nonnull Generic expression) {
final Set<Constant> notSystemConstants = new HashSet<Constant>();
@Nonnull
public static Set<Constant> getNotSystemConstants(@Nonnull Generic expression) {
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : expression.getConstants()) {
IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(constant.getName());
if (var != null && !var.isSystem() && !var.isDefined()) {
notSystemConstants.add(constant);
}
}
for (Constant constant : expression.getConstants()) {
IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(constant.getName());
if (var != null && !var.isSystem() && !var.isDefined()) {
notSystemConstants.add(constant);
}
}
return notSystemConstants;
}
return notSystemConstants;
}
}

View File

@@ -22,11 +22,6 @@
package org.solovyev.android.calculator;
import jscl.math.function.IConstant;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.model.MathEntityBuilder;
import org.solovyev.android.calculator.model.Var;
import org.solovyev.android.calculator.model.Vars;
@@ -37,6 +32,11 @@ import org.solovyev.common.math.MathRegistry;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.IConstant;
/**
* User: serso
* Date: 9/29/11
@@ -44,110 +44,110 @@ import java.util.Map;
*/
public class CalculatorVarsRegistry extends AbstractCalculatorMathRegistry<IConstant, Var> {
@Nonnull
public static final String ANS = "ans";
@Nonnull
public static final String ANS = "ans";
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
static {
substitutes.put("π", "pi");
substitutes.put("Π", "PI");
substitutes.put("", "inf");
substitutes.put("h", "h_reduced");
substitutes.put("NaN", "nan");
}
static {
substitutes.put("π", "pi");
substitutes.put("Π", "PI");
substitutes.put("", "inf");
substitutes.put("h", "h_reduced");
substitutes.put("NaN", "nan");
}
public CalculatorVarsRegistry(@Nonnull MathRegistry<IConstant> mathRegistry,
@Nonnull MathEntityDao<Var> mathEntityDao) {
super(mathRegistry, "c_var_description_", mathEntityDao);
}
public CalculatorVarsRegistry(@Nonnull MathRegistry<IConstant> mathRegistry,
@Nonnull MathEntityDao<Var> mathEntityDao) {
super(mathRegistry, "c_var_description_", mathEntityDao);
}
public static <T extends MathEntity> void saveVariable(@Nonnull CalculatorMathRegistry<T> registry,
@Nonnull MathEntityBuilder<? extends T> builder,
@Nullable T editedInstance,
@Nonnull Object source, boolean save) {
final T addedVar = registry.add(builder);
public static <T extends MathEntity> void saveVariable(@Nonnull CalculatorMathRegistry<T> registry,
@Nonnull MathEntityBuilder<? extends T> builder,
@Nullable T editedInstance,
@Nonnull Object source, boolean save) {
final T addedVar = registry.add(builder);
if (save) {
registry.save();
}
if (save) {
registry.save();
}
if (editedInstance == null) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_added, addedVar, source);
} else {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_changed, ChangeImpl.newInstance(editedInstance, addedVar), source);
}
}
if (editedInstance == null) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_added, addedVar, source);
} else {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_changed, ChangeImpl.newInstance(editedInstance, addedVar), source);
}
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
@Nonnull
@Override
protected Map<String, String> getSubstitutes() {
return substitutes;
}
public synchronized void load() {
super.load();
public synchronized void load() {
super.load();
tryToAddAuxVar("x");
tryToAddAuxVar("y");
tryToAddAuxVar("t");
tryToAddAuxVar("j");
tryToAddAuxVar("x");
tryToAddAuxVar("y");
tryToAddAuxVar("t");
tryToAddAuxVar("j");
/*Log.d(AndroidVarsRegistry.class.getName(), vars.size() + " variables registered!");
for (Var var : vars) {
for (Var var : vars) {
Log.d(AndroidVarsRegistry.class.getName(), var.toString());
}*/
}
}
@Nonnull
@Override
protected JBuilder<? extends IConstant> createBuilder(@Nonnull Var entity) {
return new Var.Builder(entity);
}
@Nonnull
@Override
protected JBuilder<? extends IConstant> createBuilder(@Nonnull Var entity) {
return new Var.Builder(entity);
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<Var> createPersistenceContainer() {
return new Vars();
}
@Nonnull
@Override
protected MathEntityPersistenceContainer<Var> createPersistenceContainer() {
return new Vars();
}
private void tryToAddAuxVar(@Nonnull String name) {
if (!contains(name)) {
add(new Var.Builder(name, (String) null));
}
}
private void tryToAddAuxVar(@Nonnull String name) {
if (!contains(name)) {
add(new Var.Builder(name, (String) null));
}
}
@Nonnull
@Override
protected Var transform(@Nonnull IConstant entity) {
if (entity instanceof Var) {
return (Var) entity;
} else {
return new Var.Builder(entity).create();
}
}
@Nonnull
@Override
protected Var transform(@Nonnull IConstant entity) {
if (entity instanceof Var) {
return (Var) entity;
} else {
return new Var.Builder(entity).create();
}
}
@Override
public String getDescription(@Nonnull String mathEntityName) {
final IConstant var = get(mathEntityName);
if (var != null && !var.isSystem()) {
return var.getDescription();
} else {
return super.getDescription(mathEntityName);
}
}
@Override
public String getDescription(@Nonnull String mathEntityName) {
final IConstant var = get(mathEntityName);
if (var != null && !var.isSystem()) {
return var.getDescription();
} else {
return super.getDescription(mathEntityName);
}
}
@Override
public String getCategory(@Nonnull IConstant var) {
for (VarCategory category : VarCategory.values()) {
if (category.isInCategory(var)) {
return category.name();
}
}
@Override
public String getCategory(@Nonnull IConstant var) {
for (VarCategory category : VarCategory.values()) {
if (category.isInCategory(var)) {
return category.name();
}
}
return null;
}
return null;
}
}

View File

@@ -31,10 +31,10 @@ import javax.annotation.Nonnull;
*/
public interface Change<T> {
@Nonnull
T getOldValue();
@Nonnull
T getOldValue();
@Nonnull
T getNewValue();
@Nonnull
T getNewValue();
}

View File

@@ -31,34 +31,34 @@ import javax.annotation.Nonnull;
*/
public class ChangeImpl<T> implements Change<T> {
@Nonnull
private T oldValue;
@Nonnull
private T oldValue;
@Nonnull
private T newValue;
@Nonnull
private T newValue;
private ChangeImpl() {
}
private ChangeImpl() {
}
@Nonnull
public static <T> Change<T> newInstance(@Nonnull T oldValue, @Nonnull T newValue) {
final ChangeImpl<T> result = new ChangeImpl<T>();
@Nonnull
public static <T> Change<T> newInstance(@Nonnull T oldValue, @Nonnull T newValue) {
final ChangeImpl<T> result = new ChangeImpl<T>();
result.oldValue = oldValue;
result.newValue = newValue;
result.oldValue = oldValue;
result.newValue = newValue;
return result;
}
return result;
}
@Nonnull
@Override
public T getOldValue() {
return this.oldValue;
}
@Nonnull
@Override
public T getOldValue() {
return this.oldValue;
}
@Nonnull
@Override
public T getNewValue() {
return this.newValue;
}
@Nonnull
@Override
public T getNewValue() {
return this.newValue;
}
}

View File

@@ -31,6 +31,6 @@ import javax.annotation.Nonnull;
*/
public interface ConversionFailure {
@Nonnull
Exception getException();
@Nonnull
Exception getException();
}

View File

@@ -31,16 +31,16 @@ import javax.annotation.Nonnull;
*/
public class ConversionFailureImpl implements ConversionFailure {
@Nonnull
private Exception exception;
@Nonnull
private Exception exception;
public ConversionFailureImpl(@Nonnull Exception exception) {
this.exception = exception;
}
public ConversionFailureImpl(@Nonnull Exception exception) {
this.exception = exception;
}
@Nonnull
@Override
public Exception getException() {
return this.exception;
}
@Nonnull
@Override
public Exception getException() {
return this.exception;
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import org.solovyev.common.msg.MessageLevel;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.MessageLevel;
/**
* User: serso
* Date: 1/20/13
@@ -34,12 +34,12 @@ import org.solovyev.common.msg.MessageLevel;
*/
public interface DialogData {
@Nonnull
String getMessage();
@Nonnull
String getMessage();
@Nonnull
MessageLevel getMessageLevel();
@Nonnull
MessageLevel getMessageLevel();
@Nullable
String getTitle();
@Nullable
String getTitle();
}

View File

@@ -31,16 +31,16 @@ import javax.annotation.Nonnull;
*/
public class DummyCalculatorClipboard implements CalculatorClipboard {
@Override
public String getText() {
return null;
}
@Override
public String getText() {
return null;
}
@Override
public void setText(@Nonnull String text) {
}
@Override
public void setText(@Nonnull CharSequence text) {
}
@Override
public void setText(@Nonnull CharSequence text) {
}
@Override
public void setText(@Nonnull String text) {
}
}

View File

@@ -22,14 +22,14 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 9/22/12
@@ -37,19 +37,19 @@ import java.util.List;
*/
public class DummyCalculatorNotifier implements CalculatorNotifier {
@Override
public void showMessage(@Nonnull Message message) {
}
@Override
public void showMessage(@Nonnull Message message) {
}
@Override
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters) {
}
@Override
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters) {
}
@Override
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
}
@Override
public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) {
}
@Override
public void showDebugMessage(@Nullable String tag, @Nonnull String message) {
}
@Override
public void showDebugMessage(@Nullable String tag, @Nonnull String message) {
}
}

View File

@@ -31,13 +31,13 @@ import javax.annotation.Nullable;
*/
public interface Editor {
@Nullable
CharSequence getText();
@Nullable
CharSequence getText();
void setText(@Nullable CharSequence text);
void setText(@Nullable CharSequence text);
int getSelection();
int getSelection();
void setSelection(int selection);
void setSelection(int selection);
}

View File

@@ -22,10 +22,10 @@
package org.solovyev.android.calculator;
import javax.annotation.Nullable;
import java.io.Serializable;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/2/12
@@ -33,8 +33,8 @@ import java.io.Serializable;
*/
public interface FixableError extends Serializable {
@Nullable
CharSequence getFixCaption();
@Nullable
CharSequence getFixCaption();
void fix();
void fix();
}

View File

@@ -22,19 +22,19 @@
package org.solovyev.android.calculator;
import jscl.math.function.ArcTrigonometric;
import jscl.math.function.Comparison;
import jscl.math.function.Function;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
import org.solovyev.common.collections.Collections;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.ArcTrigonometric;
import jscl.math.function.Comparison;
import jscl.math.function.Function;
import jscl.math.function.Trigonometric;
/**
* User: serso
* Date: 10/7/12
@@ -42,71 +42,71 @@ import java.util.List;
*/
public enum FunctionCategory {
trigonometric(100) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return (function instanceof Trigonometric || function instanceof ArcTrigonometric) && !hyperbolic_trigonometric.isInCategory(function);
}
},
trigonometric(100) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return (function instanceof Trigonometric || function instanceof ArcTrigonometric) && !hyperbolic_trigonometric.isInCategory(function);
}
},
hyperbolic_trigonometric(300) {
hyperbolic_trigonometric(300) {
private final List<String> names = Arrays.asList("sinh", "cosh", "tanh", "coth", "asinh", "acosh", "atanh", "acoth");
private final List<String> names = Arrays.asList("sinh", "cosh", "tanh", "coth", "asinh", "acosh", "atanh", "acoth");
@Override
public boolean isInCategory(@Nonnull Function function) {
return names.contains(function.getName());
}
},
@Override
public boolean isInCategory(@Nonnull Function function) {
return names.contains(function.getName());
}
},
comparison(200) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return function instanceof Comparison;
}
},
comparison(200) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return function instanceof Comparison;
}
},
my(0) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return !function.isSystem();
}
},
my(0) {
@Override
public boolean isInCategory(@Nonnull Function function) {
return !function.isSystem();
}
},
common(50) {
@Override
public boolean isInCategory(@Nonnull Function function) {
for (FunctionCategory category : values()) {
if (category != this) {
if (category.isInCategory(function)) {
return false;
}
}
}
common(50) {
@Override
public boolean isInCategory(@Nonnull Function function) {
for (FunctionCategory category : values()) {
if (category != this) {
if (category.isInCategory(function)) {
return false;
}
}
}
return true;
}
};
return true;
}
};
private final int tabOrder;
private final int tabOrder;
FunctionCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
FunctionCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
public abstract boolean isInCategory(@Nonnull Function function);
@Nonnull
public static List<FunctionCategory> getCategoriesByTabOrder() {
final List<FunctionCategory> result = Collections.asList(FunctionCategory.values());
@Nonnull
public static List<FunctionCategory> getCategoriesByTabOrder() {
final List<FunctionCategory> result = Collections.asList(FunctionCategory.values());
java.util.Collections.sort(result, new Comparator<FunctionCategory>() {
@Override
public int compare(FunctionCategory category, FunctionCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
java.util.Collections.sort(result, new Comparator<FunctionCategory>() {
@Override
public int compare(FunctionCategory category, FunctionCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
return result;
}
return result;
}
public abstract boolean isInCategory(@Nonnull Function function);
}

View File

@@ -22,9 +22,6 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.listeners.JListeners;
import org.solovyev.common.listeners.Listeners;
@@ -32,6 +29,9 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -39,45 +39,45 @@ import java.util.List;
*/
public class ListCalculatorEventContainer implements CalculatorEventContainer {
@Nonnull
private static final String TAG = "CalculatorEventData";
@Nonnull
private static final String TAG = "CalculatorEventData";
@Nonnull
private final JListeners<CalculatorEventListener> listeners = Listeners.newWeakRefListeners();
@Nonnull
private final JListeners<CalculatorEventListener> listeners = Listeners.newWeakRefListeners();
@Override
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
listeners.addListener(calculatorEventListener);
}
@Override
public void addCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
listeners.addListener(calculatorEventListener);
}
@Override
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
listeners.removeListener(calculatorEventListener);
}
@Override
public void removeCalculatorEventListener(@Nonnull CalculatorEventListener calculatorEventListener) {
listeners.removeListener(calculatorEventListener);
}
@Override
public void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
fireCalculatorEvents(Arrays.asList(new CalculatorEvent(calculatorEventData, calculatorEventType, data)));
}
@Override
public void fireCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
fireCalculatorEvents(Arrays.asList(new CalculatorEvent(calculatorEventData, calculatorEventType, data)));
}
@Override
public void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents) {
final Collection<CalculatorEventListener> listeners = this.listeners.getListeners();
@Override
public void fireCalculatorEvents(@Nonnull List<CalculatorEvent> calculatorEvents) {
final Collection<CalculatorEventListener> listeners = this.listeners.getListeners();
//final CalculatorLogger logger = Locator.getInstance().getLogger();
//final CalculatorLogger logger = Locator.getInstance().getLogger();
for (CalculatorEvent e : calculatorEvents) {
//Locator.getInstance().getLogger().debug(TAG, "Event fired: " + e.getCalculatorEventType());
for (CalculatorEventListener listener : listeners) {
/*long startTime = System.currentTimeMillis();*/
listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData());
for (CalculatorEvent e : calculatorEvents) {
//Locator.getInstance().getLogger().debug(TAG, "Event fired: " + e.getCalculatorEventType());
for (CalculatorEventListener listener : listeners) {
/*long startTime = System.currentTimeMillis();*/
listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData());
/* long endTime = System.currentTimeMillis();
long totalTime = (endTime - startTime);
if ( totalTime > 300 ) {
logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Started event: " + e.getCalculatorEventType() + " with data: " + e.getData() + " for: " + listener.getClass().getSimpleName());
logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Total time, ms: " + totalTime);
}*/
}
}
}
}
}
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import jscl.NumeralBase;
import org.solovyev.android.calculator.math.MathType;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.math.MathType;
import jscl.NumeralBase;
/**
* User: serso
@@ -36,37 +36,37 @@ import org.solovyev.android.calculator.math.MathType;
public class LiteNumberBuilder extends AbstractNumberBuilder {
public LiteNumberBuilder(@Nonnull CalculatorEngine engine) {
super(engine);
this.nb = engine.getNumeralBase();
}
public LiteNumberBuilder(@Nonnull CalculatorEngine engine) {
super(engine);
this.nb = engine.getNumeralBase();
}
public void process(@Nonnull MathType.Result mathTypeResult) {
if (canContinue(mathTypeResult)) {
// let's continue building number
if (numberBuilder == null) {
// if new number => create new builder
numberBuilder = new StringBuilder();
}
public void process(@Nonnull MathType.Result mathTypeResult) {
if (canContinue(mathTypeResult)) {
// let's continue building number
if (numberBuilder == null) {
// if new number => create new builder
numberBuilder = new StringBuilder();
}
if (mathTypeResult.getMathType() != MathType.numeral_base) {
// just add matching string
numberBuilder.append(mathTypeResult.getMatch());
} else {
// set explicitly numeral base (do not include it into number)
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
}
if (mathTypeResult.getMathType() != MathType.numeral_base) {
// just add matching string
numberBuilder.append(mathTypeResult.getMatch());
} else {
// set explicitly numeral base (do not include it into number)
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
}
} else {
// process current number (and go to the next one)
if (numberBuilder != null) {
numberBuilder = null;
} else {
// process current number (and go to the next one)
if (numberBuilder != null) {
numberBuilder = null;
// must set default numeral base (exit numeral base mode)
nb = engine.getNumeralBase();
}
}
}
// must set default numeral base (exit numeral base mode)
nb = engine.getNumeralBase();
}
}
}
}

View File

@@ -37,143 +37,133 @@ import javax.annotation.Nullable;
*/
public class Locator implements CalculatorLocator {
@Nonnull
private CalculatorEngine calculatorEngine;
@Nonnull
private static final Locator instance = new Locator();
@Nonnull
private CalculatorEngine calculatorEngine;
@Nonnull
private Calculator calculator;
@Nonnull
private CalculatorEditor calculatorEditor;
@Nonnull
private CalculatorDisplay calculatorDisplay;
@Nonnull
private CalculatorKeyboard calculatorKeyboard;
@Nonnull
private CalculatorHistory calculatorHistory;
@Nonnull
private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier();
@Nonnull
private CalculatorLogger calculatorLogger = new SystemOutCalculatorLogger();
@Nonnull
private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard();
@Nonnull
private CalculatorPreferenceService calculatorPreferenceService;
@Nonnull
private Calculator calculator;
@Nonnull
private CalculatorPlotter calculatorPlotter;
@Nonnull
private CalculatorEditor calculatorEditor;
public Locator() {
}
@Nonnull
private CalculatorDisplay calculatorDisplay;
@Nonnull
public static CalculatorLocator getInstance() {
return instance;
}
@Nonnull
private CalculatorKeyboard calculatorKeyboard;
@Override
public void init(@Nonnull Calculator calculator,
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull CalculatorHistory history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor) {
@Nonnull
private CalculatorHistory calculatorHistory;
this.calculator = calculator;
this.calculatorEngine = engine;
this.calculatorClipboard = clipboard;
this.calculatorNotifier = notifier;
this.calculatorHistory = history;
this.calculatorLogger = logger;
this.calculatorPreferenceService = preferenceService;
this.calculatorPlotter = plotter;
@Nonnull
private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier();
calculatorEditor = new CalculatorEditorImpl(this.calculator, editorTextProcessor);
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
calculatorKeyboard = keyboard;
}
@Nonnull
private CalculatorLogger calculatorLogger = new SystemOutCalculatorLogger();
@Nonnull
@Override
public CalculatorEngine getEngine() {
return calculatorEngine;
}
@Nonnull
private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard();
@Nonnull
@Override
public Calculator getCalculator() {
return this.calculator;
}
@Nonnull
private static final Locator instance = new Locator();
@Override
@Nonnull
public CalculatorDisplay getDisplay() {
return calculatorDisplay;
}
@Nonnull
private CalculatorPreferenceService calculatorPreferenceService;
@Nonnull
@Override
public CalculatorEditor getEditor() {
return calculatorEditor;
}
@Nonnull
private CalculatorPlotter calculatorPlotter;
@Override
@Nonnull
public CalculatorKeyboard getKeyboard() {
return calculatorKeyboard;
}
public Locator() {
}
public static void setKeyboard(@Nonnull CalculatorKeyboard keyboard) {
instance.calculatorKeyboard = keyboard;
}
@Override
public void init(@Nonnull Calculator calculator,
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull CalculatorHistory history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor) {
@Override
@Nonnull
public CalculatorClipboard getClipboard() {
return calculatorClipboard;
}
this.calculator = calculator;
this.calculatorEngine = engine;
this.calculatorClipboard = clipboard;
this.calculatorNotifier = notifier;
this.calculatorHistory = history;
this.calculatorLogger = logger;
this.calculatorPreferenceService = preferenceService;
this.calculatorPlotter = plotter;
@Override
@Nonnull
public CalculatorNotifier getNotifier() {
return calculatorNotifier;
}
calculatorEditor = new CalculatorEditorImpl(this.calculator, editorTextProcessor);
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
calculatorKeyboard = keyboard;
}
@Override
@Nonnull
public CalculatorHistory getHistory() {
return calculatorHistory;
}
@Nonnull
public static CalculatorLocator getInstance() {
return instance;
}
@Override
@Nonnull
public CalculatorLogger getLogger() {
return calculatorLogger;
}
@Nonnull
@Override
public CalculatorEngine getEngine() {
return calculatorEngine;
}
@Nonnull
@Override
public CalculatorPlotter getPlotter() {
return calculatorPlotter;
}
@Nonnull
@Override
public Calculator getCalculator() {
return this.calculator;
}
@Override
@Nonnull
public CalculatorDisplay getDisplay() {
return calculatorDisplay;
}
@Nonnull
@Override
public CalculatorEditor getEditor() {
return calculatorEditor;
}
@Override
@Nonnull
public CalculatorKeyboard getKeyboard() {
return calculatorKeyboard;
}
@Override
@Nonnull
public CalculatorClipboard getClipboard() {
return calculatorClipboard;
}
@Override
@Nonnull
public CalculatorNotifier getNotifier() {
return calculatorNotifier;
}
@Override
@Nonnull
public CalculatorHistory getHistory() {
return calculatorHistory;
}
@Override
@Nonnull
public CalculatorLogger getLogger() {
return calculatorLogger;
}
@Nonnull
@Override
public CalculatorPlotter getPlotter() {
return calculatorPlotter;
}
@Nonnull
@Override
public CalculatorPreferenceService getPreferenceService() {
return this.calculatorPreferenceService;
}
public static void setKeyboard(@Nonnull CalculatorKeyboard keyboard) {
instance.calculatorKeyboard = keyboard;
}
@Nonnull
@Override
public CalculatorPreferenceService getPreferenceService() {
return this.calculatorPreferenceService;
}
}

View File

@@ -32,11 +32,11 @@ import javax.annotation.Nullable;
*/
public interface MathEntityDao<T extends MathPersistenceEntity> {
void save(@Nonnull MathEntityPersistenceContainer<T> container);
void save(@Nonnull MathEntityPersistenceContainer<T> container);
@Nullable
MathEntityPersistenceContainer<T> load();
@Nullable
MathEntityPersistenceContainer<T> load();
@Nullable
String getDescription(@Nonnull String descriptionId);
@Nullable
String getDescription(@Nonnull String descriptionId);
}

View File

@@ -31,6 +31,6 @@ import java.util.List;
*/
public interface MathEntityPersistenceContainer<T extends MathPersistenceEntity> {
public List<T> getEntities();
public List<T> getEntities();
}

View File

@@ -31,6 +31,6 @@ import javax.annotation.Nonnull;
*/
public interface MathPersistenceEntity {
@Nonnull
String getName();
@Nonnull
String getName();
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageLevel;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 1/20/13
@@ -35,37 +35,37 @@ import org.solovyev.common.msg.MessageLevel;
*/
public class MessageDialogData implements DialogData {
@Nonnull
private Message message;
@Nonnull
private Message message;
@Nullable
private String title;
@Nullable
private String title;
private MessageDialogData(@Nonnull Message message, @Nullable String title) {
this.message = message;
this.title = title;
}
private MessageDialogData(@Nonnull Message message, @Nullable String title) {
this.message = message;
this.title = title;
}
@Nonnull
public static DialogData newInstance(@Nonnull Message message, @Nullable String title) {
return new MessageDialogData(message, title);
}
@Nonnull
public static DialogData newInstance(@Nonnull Message message, @Nullable String title) {
return new MessageDialogData(message, title);
}
@Override
@Nonnull
public String getMessage() {
return message.getLocalizedMessage();
}
@Override
@Nonnull
public String getMessage() {
return message.getLocalizedMessage();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return message.getMessageLevel();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return message.getMessageLevel();
}
@Override
@Nullable
public String getTitle() {
return title;
}
@Override
@Nullable
public String getTitle() {
return title;
}
}

View File

@@ -22,21 +22,25 @@
package org.solovyev.android.calculator;
import jscl.MathContext;
import jscl.MathEngine;
import jscl.NumeralBase;
import jscl.math.numeric.Real;
import jscl.text.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.MutableObject;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.MathContext;
import jscl.MathEngine;
import jscl.NumeralBase;
import jscl.math.numeric.Real;
import jscl.text.DoubleParser;
import jscl.text.JsclIntegerParser;
import jscl.text.MutableInt;
import jscl.text.ParseException;
import jscl.text.Parser;
/**
* User: serso
* Date: 10/23/11
@@ -44,174 +48,174 @@ import java.util.List;
*/
public class NumberBuilder extends AbstractNumberBuilder {
public NumberBuilder(@Nonnull CalculatorEngine engine) {
super(engine);
}
public NumberBuilder(@Nonnull CalculatorEngine engine) {
super(engine);
}
/**
* Method replaces number in text according to some rules (e.g. formatting)
*
* @param text text where number can be replaced
* @param mathTypeResult math type result of current token
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
* @return new math type result (as one can be changed due to substituting of number with constant)
*/
@Nonnull
public MathType.Result process(@Nonnull StringBuilder text, @Nonnull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
final MathType.Result possibleResult;
if (canContinue(mathTypeResult)) {
// let's continue building number
if (numberBuilder == null) {
// if new number => create new builder
numberBuilder = new StringBuilder();
}
@Nullable
private static MathType.Result replaceNumberInText(@Nonnull StringBuilder text,
@Nullable String number,
int trimmedChars,
@Nullable MutableObject<Integer> offset,
@Nonnull NumeralBase nb,
@Nonnull final MathEngine engine) {
MathType.Result result = null;
if (mathTypeResult.getMathType() != MathType.numeral_base) {
// just add matching string
numberBuilder.append(mathTypeResult.getMatch());
} else {
// set explicitly numeral base (do not include it into number)
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
}
if (number != null) {
// in any case remove old number from text
final int oldNumberLength = number.length() + trimmedChars;
text.delete(text.length() - oldNumberLength, text.length());
possibleResult = null;
} else {
// process current number (and go to the next one)
possibleResult = processNumber(text, offset);
}
final String newNumber = formatNumber(number, nb, engine);
if (offset != null) {
// register offset between old number and new number
offset.setObject(newNumber.length() - oldNumberLength);
}
text.append(newNumber);
}
return possibleResult == null ? mathTypeResult : possibleResult;
}
return result;
}
/**
* Method replaces number in text according to some rules (e.g. formatting)
*
* @param text text where number can be replaced
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
* @return new math type result (as one can be changed due to substituting of number with constant)
*/
@Nullable
public MathType.Result processNumber(@Nonnull StringBuilder text, @Nullable MutableObject<Integer> offset) {
// total number of trimmed chars
int trimmedChars = 0;
@Nonnull
private static String formatNumber(@Nonnull String number, @Nonnull NumeralBase nb, @Nonnull MathEngine engine) {
String result;
String number = null;
int indexOfDot = number.indexOf('.');
// toXml numeral base (as later it might be replaced)
final NumeralBase localNb = getNumeralBase();
if (indexOfDot < 0) {
int indexOfE;
if (nb == NumeralBase.hex) {
indexOfE = -1;
} else {
indexOfE = number.indexOf(MathType.POWER_10);
}
if (indexOfE < 0) {
result = engine.addGroupingSeparators(nb, number);
} else {
final String partBeforeE;
if (indexOfE != 0) {
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
} else {
partBeforeE = "";
}
result = partBeforeE + number.substring(indexOfE);
}
} else {
final String integerPart;
if (indexOfDot != 0) {
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
} else {
integerPart = "";
}
result = integerPart + number.substring(indexOfDot);
}
if (numberBuilder != null) {
try {
number = numberBuilder.toString();
return result;
}
// let's get rid of unnecessary characters (grouping separators, + after E)
final List<String> tokens = new ArrayList<String>();
tokens.addAll(MathType.grouping_separator.getTokens());
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
tokens.add("+");
for (String groupingSeparator : tokens) {
final String trimmedNumber = number.replace(groupingSeparator, "");
trimmedChars += number.length() - trimmedNumber.length();
number = trimmedNumber;
}
@Nonnull
private static Double toDouble(@Nonnull String s, @Nonnull NumeralBase nb, @Nonnull final MathContext mc) throws NumberFormatException {
final NumeralBase defaultNb = mc.getNumeralBase();
try {
mc.setNumeralBase(nb);
// check if number still valid
toDouble(number, getNumeralBase(), engine.getMathEngine0());
try {
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
} catch (ParseException e) {
try {
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
} catch (ParseException e1) {
throw new NumberFormatException();
}
}
} catch (NumberFormatException e) {
// number is not valid => stop
number = null;
}
} finally {
mc.setNumeralBase(defaultNb);
}
}
numberBuilder = null;
/**
* Method replaces number in text according to some rules (e.g. formatting)
*
* @param text text where number can be replaced
* @param mathTypeResult math type result of current token
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
* @return new math type result (as one can be changed due to substituting of number with constant)
*/
@Nonnull
public MathType.Result process(@Nonnull StringBuilder text, @Nonnull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
final MathType.Result possibleResult;
if (canContinue(mathTypeResult)) {
// let's continue building number
if (numberBuilder == null) {
// if new number => create new builder
numberBuilder = new StringBuilder();
}
// must set default numeral base (exit numeral base mode)
nb = engine.getNumeralBase();
}
if (mathTypeResult.getMathType() != MathType.numeral_base) {
// just add matching string
numberBuilder.append(mathTypeResult.getMatch());
} else {
// set explicitly numeral base (do not include it into number)
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
}
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine.getMathEngine0());
}
possibleResult = null;
} else {
// process current number (and go to the next one)
possibleResult = processNumber(text, offset);
}
@Nullable
private static MathType.Result replaceNumberInText(@Nonnull StringBuilder text,
@Nullable String number,
int trimmedChars,
@Nullable MutableObject<Integer> offset,
@Nonnull NumeralBase nb,
@Nonnull final MathEngine engine) {
MathType.Result result = null;
return possibleResult == null ? mathTypeResult : possibleResult;
}
if (number != null) {
// in any case remove old number from text
final int oldNumberLength = number.length() + trimmedChars;
text.delete(text.length() - oldNumberLength, text.length());
/**
* Method replaces number in text according to some rules (e.g. formatting)
*
* @param text text where number can be replaced
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
* @return new math type result (as one can be changed due to substituting of number with constant)
*/
@Nullable
public MathType.Result processNumber(@Nonnull StringBuilder text, @Nullable MutableObject<Integer> offset) {
// total number of trimmed chars
int trimmedChars = 0;
final String newNumber = formatNumber(number, nb, engine);
if (offset != null) {
// register offset between old number and new number
offset.setObject(newNumber.length() - oldNumberLength);
}
text.append(newNumber);
}
String number = null;
return result;
}
// toXml numeral base (as later it might be replaced)
final NumeralBase localNb = getNumeralBase();
@Nonnull
private static String formatNumber(@Nonnull String number, @Nonnull NumeralBase nb, @Nonnull MathEngine engine) {
String result;
if (numberBuilder != null) {
try {
number = numberBuilder.toString();
int indexOfDot = number.indexOf('.');
// let's get rid of unnecessary characters (grouping separators, + after E)
final List<String> tokens = new ArrayList<String>();
tokens.addAll(MathType.grouping_separator.getTokens());
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
tokens.add("+");
for (String groupingSeparator : tokens) {
final String trimmedNumber = number.replace(groupingSeparator, "");
trimmedChars += number.length() - trimmedNumber.length();
number = trimmedNumber;
}
if (indexOfDot < 0) {
int indexOfE;
if (nb == NumeralBase.hex) {
indexOfE = -1;
} else {
indexOfE = number.indexOf(MathType.POWER_10);
}
if (indexOfE < 0) {
result = engine.addGroupingSeparators(nb, number);
} else {
final String partBeforeE;
if (indexOfE != 0) {
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
} else {
partBeforeE = "";
}
result = partBeforeE + number.substring(indexOfE);
}
} else {
final String integerPart;
if (indexOfDot != 0) {
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
} else {
integerPart = "";
}
result = integerPart + number.substring(indexOfDot);
}
// check if number still valid
toDouble(number, getNumeralBase(), engine.getMathEngine0());
return result;
}
} catch (NumberFormatException e) {
// number is not valid => stop
number = null;
}
@Nonnull
private static Double toDouble(@Nonnull String s, @Nonnull NumeralBase nb, @Nonnull final MathContext mc) throws NumberFormatException {
final NumeralBase defaultNb = mc.getNumeralBase();
try {
mc.setNumeralBase(nb);
numberBuilder = null;
try {
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
} catch (ParseException e) {
try {
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
} catch (ParseException e1) {
throw new NumberFormatException();
}
}
// must set default numeral base (exit numeral base mode)
nb = engine.getNumeralBase();
}
} finally {
mc.setNumeralBase(defaultNb);
}
}
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine.getMathEngine0());
}
}

View File

@@ -22,15 +22,20 @@
package org.solovyev.android.calculator;
import jscl.math.operator.*;
import javax.annotation.Nonnull;
import org.solovyev.common.collections.Collections;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.operator.Derivative;
import jscl.math.operator.IndefiniteIntegral;
import jscl.math.operator.Integral;
import jscl.math.operator.Operator;
import jscl.math.operator.Product;
import jscl.math.operator.Sum;
/**
* User: serso
* Date: 10/7/12
@@ -38,64 +43,64 @@ import java.util.List;
*/
public enum OperatorCategory {
derivatives(100) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Derivative || operator instanceof Integral || operator instanceof IndefiniteIntegral;
}
},
derivatives(100) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Derivative || operator instanceof Integral || operator instanceof IndefiniteIntegral;
}
},
other(200) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Sum || operator instanceof Product;
}
},
other(200) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return operator instanceof Sum || operator instanceof Product;
}
},
my(0) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return !operator.isSystem();
}
},
my(0) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
return !operator.isSystem();
}
},
common(50) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
for (OperatorCategory category : values()) {
if (category != this) {
if (category.isInCategory(operator)) {
return false;
}
}
}
common(50) {
@Override
public boolean isInCategory(@Nonnull Operator operator) {
for (OperatorCategory category : values()) {
if (category != this) {
if (category.isInCategory(operator)) {
return false;
}
}
}
return true;
}
};
return true;
}
};
private final int tabOrder;
private final int tabOrder;
OperatorCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
OperatorCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
public abstract boolean isInCategory(@Nonnull Operator operator);
@Nonnull
public static List<OperatorCategory> getCategoriesByTabOrder() {
final List<OperatorCategory> result = Collections.asList(OperatorCategory.values());
@Nonnull
public static List<OperatorCategory> getCategoriesByTabOrder() {
final List<OperatorCategory> result = Collections.asList(OperatorCategory.values());
java.util.Collections.sort(result, new Comparator<OperatorCategory>() {
@Override
public int compare(OperatorCategory category, OperatorCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
java.util.Collections.sort(result, new Comparator<OperatorCategory>() {
@Override
public int compare(OperatorCategory category, OperatorCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
// todo serso: current solution (as creating operators is not implemented yet)
result.remove(my);
// todo serso: current solution (as creating operators is not implemented yet)
result.remove(my);
return result;
}
return result;
}
public abstract boolean isInCategory(@Nonnull Operator operator);
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import jscl.math.function.IConstant;
import java.util.List;
import javax.annotation.Nonnull;
import java.util.List;
import jscl.math.function.IConstant;
/**
* User: serso
@@ -35,48 +35,48 @@ import java.util.List;
*/
public class PreparedExpression implements CharSequence {
@Nonnull
private String expression;
@Nonnull
private String expression;
@Nonnull
private List<IConstant> undefinedVars;
@Nonnull
private List<IConstant> undefinedVars;
public PreparedExpression(@Nonnull String expression, @Nonnull List<IConstant> undefinedVars) {
this.expression = expression;
this.undefinedVars = undefinedVars;
}
public PreparedExpression(@Nonnull String expression, @Nonnull List<IConstant> undefinedVars) {
this.expression = expression;
this.undefinedVars = undefinedVars;
}
@Nonnull
public String getExpression() {
return expression;
}
@Nonnull
public String getExpression() {
return expression;
}
public boolean isExistsUndefinedVar() {
return !this.undefinedVars.isEmpty();
}
public boolean isExistsUndefinedVar() {
return !this.undefinedVars.isEmpty();
}
@Nonnull
public List<IConstant> getUndefinedVars() {
return undefinedVars;
}
@Nonnull
public List<IConstant> getUndefinedVars() {
return undefinedVars;
}
@Override
public int length() {
return expression.length();
}
@Override
public int length() {
return expression.length();
}
@Override
public char charAt(int i) {
return expression.charAt(i);
}
@Override
public char charAt(int i) {
return expression.charAt(i);
}
@Override
public CharSequence subSequence(int i, int i1) {
return expression.subSequence(i, i1);
}
@Override
public CharSequence subSequence(int i, int i1) {
return expression.subSequence(i, i1);
}
@Override
public String toString() {
return this.expression;
}
@Override
public String toString() {
return this.expression;
}
}

View File

@@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.msg.MessageType;
/**
* User: serso
* Date: 1/20/13
@@ -34,41 +34,41 @@ import org.solovyev.common.msg.MessageType;
*/
public class StringDialogData implements DialogData {
@Nonnull
private final String message;
@Nonnull
private final String message;
@Nonnull
private final MessageType messageType;
@Nonnull
private final MessageType messageType;
@Nullable
private final String title;
@Nullable
private final String title;
private StringDialogData(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
this.message = message;
this.messageType = messageType;
this.title = title;
}
private StringDialogData(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
this.message = message;
this.messageType = messageType;
this.title = title;
}
@Nonnull
public static DialogData newInstance(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
return new StringDialogData(message, messageType, title);
}
@Nonnull
public static DialogData newInstance(@Nonnull String message, @Nonnull MessageType messageType, @Nullable String title) {
return new StringDialogData(message, messageType, title);
}
@Nonnull
@Override
public String getMessage() {
return message;
}
@Nonnull
@Override
public String getMessage() {
return message;
}
@Nonnull
@Override
public MessageType getMessageLevel() {
return messageType;
}
@Nonnull
@Override
public MessageType getMessageLevel() {
return messageType;
}
@Nullable
@Override
public String getTitle() {
return title;
}
@Nullable
@Override
public String getTitle() {
return title;
}
}

View File

@@ -32,33 +32,33 @@ import javax.annotation.Nullable;
*/
public class SystemOutCalculatorLogger implements CalculatorLogger {
@Nonnull
private static final String TAG = SystemOutCalculatorLogger.class.getSimpleName();
@Nonnull
private static final String TAG = SystemOutCalculatorLogger.class.getSimpleName();
@Override
public void debug(@Nullable String tag, @Nullable String message) {
System.out.println(getTag(tag) + ": " + message);
}
@Override
public void debug(@Nullable String tag, @Nullable String message) {
System.out.println(getTag(tag) + ": " + message);
}
@Nonnull
private String getTag(@Nullable String tag) {
return tag != null ? tag : TAG;
}
@Nonnull
private String getTag(@Nullable String tag) {
return tag != null ? tag : TAG;
}
@Override
public void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
debug(tag, message);
e.printStackTrace(System.out);
}
@Override
public void debug(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
debug(tag, message);
e.printStackTrace(System.out);
}
@Override
public void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
System.out.println(getTag(tag) + ": " + message);
e.printStackTrace(System.out);
}
@Override
public void error(@Nullable String tag, @Nullable String message, @Nonnull Throwable e) {
System.out.println(getTag(tag) + ": " + message);
e.printStackTrace(System.out);
}
@Override
public void error(@Nullable String tag, @Nullable String message) {
System.out.println(getTag(tag) + ": " + message);
}
@Override
public void error(@Nullable String tag, @Nullable String message) {
System.out.println(getTag(tag) + ": " + message);
}
}

View File

@@ -22,147 +22,149 @@
package org.solovyev.android.calculator;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.common.collections.Collections;
import org.solovyev.common.msg.MessageType;
import org.solovyev.common.search.StartsWithFinder;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, String> {
@Nonnull
private static final Integer MAX_DEPTH = 20;
@Nonnull
private static final Integer MAX_DEPTH = 20;
@Nonnull
private static final TextProcessor<PreparedExpression, String> instance = new ToJsclTextProcessor();
@Nonnull
private static final TextProcessor<PreparedExpression, String> instance = new ToJsclTextProcessor();
private ToJsclTextProcessor() {
}
private ToJsclTextProcessor() {
}
@Nonnull
public static TextProcessor<PreparedExpression, String> getInstance() {
return instance;
}
@Nonnull
public static TextProcessor<PreparedExpression, String> getInstance() {
return instance;
}
@Override
@Nonnull
public PreparedExpression process(@Nonnull String s) throws CalculatorParseException {
return processWithDepth(s, 0, new ArrayList<IConstant>());
}
private static PreparedExpression processWithDepth(@Nonnull String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
return replaceVariables(processExpression(s).toString(), depth, undefinedVars);
}
private static PreparedExpression processWithDepth(@Nonnull String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
return replaceVariables(processExpression(s).toString(), depth, undefinedVars);
}
@Nonnull
private static StringBuilder processExpression(@Nonnull String s) throws CalculatorParseException {
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
final StringBuilder result = new StringBuilder();
@Nonnull
private static StringBuilder processExpression(@Nonnull String s) throws CalculatorParseException {
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
final StringBuilder result = new StringBuilder();
MathType.Result mathTypeResult = null;
MathType.Result mathTypeBefore;
MathType.Result mathTypeResult = null;
MathType.Result mathTypeBefore;
final LiteNumberBuilder nb = new LiteNumberBuilder(Locator.getInstance().getEngine());
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') continue;
startsWithFinder.setI(i);
final LiteNumberBuilder nb = new LiteNumberBuilder(Locator.getInstance().getEngine());
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') continue;
startsWithFinder.setI(i);
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult;
mathTypeBefore = mathTypeResult == null ? null : mathTypeResult;
mathTypeResult = MathType.getType(s, i, nb.isHexMode());
mathTypeResult = MathType.getType(s, i, nb.isHexMode());
nb.process(mathTypeResult);
nb.process(mathTypeResult);
if (mathTypeBefore != null) {
if (mathTypeBefore != null) {
final MathType current = mathTypeResult.getMathType();
final MathType current = mathTypeResult.getMathType();
if (current.isNeedMultiplicationSignBefore(mathTypeBefore.getMathType())) {
result.append("*");
}
}
if (current.isNeedMultiplicationSignBefore(mathTypeBefore.getMathType())) {
result.append("*");
}
}
if (mathTypeBefore != null &&
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
Collections.find(MathType.openGroupSymbols, startsWithFinder) != null) {
final String functionName = mathTypeBefore.getMatch();
final Function function = Locator.getInstance().getEngine().getFunctionsRegistry().get(functionName);
if (function == null || function.getMinParameters() > 0) {
throw new CalculatorParseException(i, s, new CalculatorMessage(CalculatorMessages.msg_005, MessageType.error, mathTypeBefore.getMatch()));
}
}
if (mathTypeBefore != null &&
(mathTypeBefore.getMathType() == MathType.function || mathTypeBefore.getMathType() == MathType.operator) &&
Collections.find(MathType.openGroupSymbols, startsWithFinder) != null) {
final String functionName = mathTypeBefore.getMatch();
final Function function = Locator.getInstance().getEngine().getFunctionsRegistry().get(functionName);
if (function == null || function.getMinParameters() > 0) {
throw new CalculatorParseException(i, s, new CalculatorMessage(CalculatorMessages.msg_005, MessageType.error, mathTypeBefore.getMatch()));
}
}
i = mathTypeResult.processToJscl(result, i);
}
return result;
}
i = mathTypeResult.processToJscl(result, i);
}
return result;
}
@Nonnull
private static PreparedExpression replaceVariables(@Nonnull final String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
if (depth >= MAX_DEPTH) {
throw new CalculatorParseException(s, new CalculatorMessage(CalculatorMessages.msg_006, MessageType.error));
} else {
depth++;
}
@Nonnull
private static PreparedExpression replaceVariables(@Nonnull final String s, int depth, @Nonnull List<IConstant> undefinedVars) throws CalculatorParseException {
if (depth >= MAX_DEPTH) {
throw new CalculatorParseException(s, new CalculatorMessage(CalculatorMessages.msg_006, MessageType.error));
} else {
depth++;
}
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
final StartsWithFinder startsWithFinder = StartsWithFinder.newInstance(s);
final StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
startsWithFinder.setI(i);
final StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
startsWithFinder.setI(i);
int offset = 0;
String functionName = Collections.find(MathType.function.getTokens(), startsWithFinder);
if (functionName == null) {
String operatorName = Collections.find(MathType.operator.getTokens(), startsWithFinder);
if (operatorName == null) {
String varName = Collections.find(Locator.getInstance().getEngine().getVarsRegistry().getNames(), startsWithFinder);
if (varName != null) {
final IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(varName);
if (var != null) {
if (!var.isDefined()) {
undefinedVars.add(var);
result.append(varName);
offset = varName.length();
} else {
final String value = var.getValue();
if (value == null) throw new AssertionError();
int offset = 0;
String functionName = Collections.find(MathType.function.getTokens(), startsWithFinder);
if (functionName == null) {
String operatorName = Collections.find(MathType.operator.getTokens(), startsWithFinder);
if (operatorName == null) {
String varName = Collections.find(Locator.getInstance().getEngine().getVarsRegistry().getNames(), startsWithFinder);
if (varName != null) {
final IConstant var = Locator.getInstance().getEngine().getVarsRegistry().get(varName);
if (var != null) {
if (!var.isDefined()) {
undefinedVars.add(var);
result.append(varName);
offset = varName.length();
} else {
final String value = var.getValue();
if (value == null) throw new AssertionError();
if (var.getDoubleValue() != null) {
//result.append(value);
// NOTE: append varName as JSCL engine will convert it to double if needed
result.append(varName);
} else {
result.append("(").append(processWithDepth(value, depth, undefinedVars)).append(")");
}
offset = varName.length();
}
}
}
} else {
result.append(operatorName);
offset = operatorName.length();
}
} else {
result.append(functionName);
offset = functionName.length();
}
if (var.getDoubleValue() != null) {
//result.append(value);
// NOTE: append varName as JSCL engine will convert it to double if needed
result.append(varName);
} else {
result.append("(").append(processWithDepth(value, depth, undefinedVars)).append(")");
}
offset = varName.length();
}
}
}
} else {
result.append(operatorName);
offset = operatorName.length();
}
} else {
result.append(functionName);
offset = functionName.length();
}
if (offset == 0) {
result.append(s.charAt(i));
} else {
i += offset - 1;
}
}
if (offset == 0) {
result.append(s.charAt(i));
} else {
i += offset - 1;
}
}
return new PreparedExpression(result.toString(), undefinedVars);
}
return new PreparedExpression(result.toString(), undefinedVars);
}
@Override
@Nonnull
public PreparedExpression process(@Nonnull String s) throws CalculatorParseException {
return processWithDepth(s, 0, new ArrayList<IConstant>());
}
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator;
import jscl.math.function.IConstant;
import javax.annotation.Nonnull;
import org.solovyev.common.collections.Collections;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.IConstant;
/**
* User: serso
* Date: 12/22/11
@@ -38,39 +38,39 @@ import java.util.List;
*/
public enum VarCategory {
system(100) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return var.isSystem();
}
},
system(100) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return var.isSystem();
}
},
my(0) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return !var.isSystem();
}
};
my(0) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return !var.isSystem();
}
};
private final int tabOrder;
private final int tabOrder;
VarCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
VarCategory(int tabOrder) {
this.tabOrder = tabOrder;
}
public abstract boolean isInCategory(@Nonnull IConstant var);
@Nonnull
public static List<VarCategory> getCategoriesByTabOrder() {
final List<VarCategory> result = Collections.asList(VarCategory.values());
@Nonnull
public static List<VarCategory> getCategoriesByTabOrder() {
final List<VarCategory> result = Collections.asList(VarCategory.values());
java.util.Collections.sort(result, new Comparator<VarCategory>() {
@Override
public int compare(VarCategory category, VarCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
java.util.Collections.sort(result, new Comparator<VarCategory>() {
@Override
public int compare(VarCategory category, VarCategory category1) {
return category.tabOrder - category1.tabOrder;
}
});
return result;
}
return result;
}
public abstract boolean isInCategory(@Nonnull IConstant var);
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator.function;
import jscl.CustomFunctionCalculationException;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import org.solovyev.android.calculator.model.AFunction;
import org.solovyev.android.calculator.model.MathEntityBuilder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.model.AFunction;
import org.solovyev.android.calculator.model.MathEntityBuilder;
import jscl.CustomFunctionCalculationException;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
/**
* User: serso
@@ -39,38 +39,38 @@ import org.solovyev.android.calculator.model.MathEntityBuilder;
*/
public final class FunctionBuilderAdapter implements MathEntityBuilder<Function> {
@Nonnull
private final AFunction.Builder nestedBuilder;
@Nonnull
private final AFunction.Builder nestedBuilder;
public FunctionBuilderAdapter(@Nonnull AFunction.Builder nestedBuilder) {
this.nestedBuilder = nestedBuilder;
}
public FunctionBuilderAdapter(@Nonnull AFunction.Builder nestedBuilder) {
this.nestedBuilder = nestedBuilder;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setName(@Nonnull String name) {
nestedBuilder.setName(name);
return this;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setName(@Nonnull String name) {
nestedBuilder.setName(name);
return this;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setDescription(@Nullable String description) {
nestedBuilder.setDescription(description);
return this;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setDescription(@Nullable String description) {
nestedBuilder.setDescription(description);
return this;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setValue(@Nullable String value) {
nestedBuilder.setValue(value);
return this;
}
@Nonnull
@Override
public MathEntityBuilder<Function> setValue(@Nullable String value) {
nestedBuilder.setValue(value);
return this;
}
@Nonnull
@Override
public Function create() throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
final AFunction function = nestedBuilder.create();
return new CustomFunction.Builder(function).create();
}
@Nonnull
@Override
public Function create() throws CustomFunctionCalculationException, AFunction.Builder.CreationException {
final AFunction function = nestedBuilder.create();
return new CustomFunction.Builder(function).create();
}
}

View File

@@ -22,13 +22,13 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Transient;
import java.util.Date;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/15/11
@@ -36,62 +36,62 @@ import java.util.Date;
*/
public class AbstractHistoryState implements Cloneable {
@Element
private long time = new Date().getTime();
@Element
private long time = new Date().getTime();
@Element(required = false)
@Nullable
private String comment;
@Element(required = false)
@Nullable
private String comment;
@Transient
private boolean saved;
@Transient
private boolean saved;
@Transient
private int id = 0;
@Transient
private int id = 0;
public int getId() {
return id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setId(int id) {
this.id = id;
}
public long getTime() {
return time;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public void setTime(long time) {
this.time = time;
}
@Nullable
public String getComment() {
return comment;
}
@Nullable
public String getComment() {
return comment;
}
public void setComment(@Nullable String comment) {
this.comment = comment;
}
public void setComment(@Nullable String comment) {
this.comment = comment;
}
public boolean isSaved() {
return saved;
}
public boolean isSaved() {
return saved;
}
public void setSaved(boolean saved) {
this.saved = saved;
}
public void setSaved(boolean saved) {
this.saved = saved;
}
@Override
protected AbstractHistoryState clone() {
AbstractHistoryState clone;
@Override
protected AbstractHistoryState clone() {
AbstractHistoryState clone;
try {
clone = (AbstractHistoryState) super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
try {
clone = (AbstractHistoryState) super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
return clone;
}
return clone;
}
}

View File

@@ -22,11 +22,6 @@
package org.solovyev.android.calculator.history;
import jscl.math.Generic;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient;
@@ -36,6 +31,11 @@ import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.Generic;
/**
* User: serso
* Date: 9/17/11
@@ -45,117 +45,117 @@ import org.solovyev.common.text.Strings;
@Root
public class CalculatorDisplayHistoryState implements Cloneable {
@Transient
private boolean valid = true;
@Transient
private boolean valid = true;
@Transient
@Nullable
private String errorMessage = null;
@Transient
@Nullable
private String errorMessage = null;
@Element
@Nonnull
private EditorHistoryState editorState;
@Element
@Nonnull
private EditorHistoryState editorState;
@Element
@Nonnull
private JsclOperation jsclOperation;
@Element
@Nonnull
private JsclOperation jsclOperation;
@Transient
@Nullable
private Generic genericResult;
@Transient
@Nullable
private Generic genericResult;
private CalculatorDisplayHistoryState() {
// for xml
}
private CalculatorDisplayHistoryState() {
// for xml
}
@Nonnull
public static CalculatorDisplayHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
@Nonnull
public static CalculatorDisplayHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
result.editorState = EditorHistoryState.newInstance(viewState);
result.editorState = EditorHistoryState.newInstance(viewState);
result.valid = viewState.isValid();
result.jsclOperation = viewState.getOperation();
result.genericResult = viewState.getResult();
result.errorMessage = viewState.getErrorMessage();
result.valid = viewState.isValid();
result.jsclOperation = viewState.getOperation();
result.genericResult = viewState.getResult();
result.errorMessage = viewState.getErrorMessage();
return result;
}
return result;
}
public void setValuesFromHistory(@Nonnull CalculatorDisplay display) {
if (this.isValid()) {
display.setViewState(CalculatorDisplayViewStateImpl.newValidState(this.getJsclOperation(), this.getGenericResult(), Strings.getNotEmpty(this.getEditorState().getText(), ""), this.getEditorState().getCursorPosition()));
} else {
display.setViewState(CalculatorDisplayViewStateImpl.newErrorState(this.getJsclOperation(), Strings.getNotEmpty(this.getErrorMessage(), "")));
}
}
public void setValuesFromHistory(@Nonnull CalculatorDisplay display) {
if (this.isValid()) {
display.setViewState(CalculatorDisplayViewStateImpl.newValidState(this.getJsclOperation(), this.getGenericResult(), Strings.getNotEmpty(this.getEditorState().getText(), ""), this.getEditorState().getCursorPosition()));
} else {
display.setViewState(CalculatorDisplayViewStateImpl.newErrorState(this.getJsclOperation(), Strings.getNotEmpty(this.getErrorMessage(), "")));
}
}
public boolean isValid() {
return valid;
}
public boolean isValid() {
return valid;
}
@Nonnull
public EditorHistoryState getEditorState() {
return editorState;
}
@Nonnull
public EditorHistoryState getEditorState() {
return editorState;
}
@Nonnull
public JsclOperation getJsclOperation() {
return jsclOperation;
}
@Nonnull
public JsclOperation getJsclOperation() {
return jsclOperation;
}
@Nullable
public String getErrorMessage() {
return errorMessage;
}
@Nullable
public String getErrorMessage() {
return errorMessage;
}
@Nullable
public Generic getGenericResult() {
return genericResult;
}
@Nullable
public Generic getGenericResult() {
return genericResult;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o;
CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o;
if (!editorState.equals(that.editorState)) return false;
if (jsclOperation != that.jsclOperation) return false;
if (!editorState.equals(that.editorState)) return false;
if (jsclOperation != that.jsclOperation) return false;
return true;
}
return true;
}
@Override
public int hashCode() {
int result = editorState.hashCode();
result = 31 * result + jsclOperation.hashCode();
return result;
}
@Override
public int hashCode() {
int result = editorState.hashCode();
result = 31 * result + jsclOperation.hashCode();
return result;
}
@Override
public String toString() {
return "CalculatorDisplayHistoryState{" +
"valid=" + valid +
", errorMessage='" + errorMessage + '\'' +
", editorHistoryState=" + editorState +
", jsclOperation=" + jsclOperation +
'}';
}
@Override
public String toString() {
return "CalculatorDisplayHistoryState{" +
"valid=" + valid +
", errorMessage='" + errorMessage + '\'' +
", editorHistoryState=" + editorState +
", jsclOperation=" + jsclOperation +
'}';
}
@Override
protected CalculatorDisplayHistoryState clone() {
try {
final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone();
@Override
protected CalculatorDisplayHistoryState clone() {
try {
final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone();
clone.editorState = this.editorState.clone();
clone.editorState = this.editorState.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -22,13 +22,13 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.common.history.HistoryHelper;
import java.util.List;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 20.09.12
@@ -36,28 +36,28 @@ import java.util.List;
*/
public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState>, CalculatorEventListener {
void load();
void load();
void save();
void save();
void fromXml(@Nonnull String xml);
void fromXml(@Nonnull String xml);
String toXml();
String toXml();
void clearSavedHistory();
void clearSavedHistory();
void removeSavedHistory(@Nonnull CalculatorHistoryState historyState);
void removeSavedHistory(@Nonnull CalculatorHistoryState historyState);
@Nonnull
List<CalculatorHistoryState> getSavedHistory();
@Nonnull
List<CalculatorHistoryState> getSavedHistory();
@Nonnull
CalculatorHistoryState addSavedState(@Nonnull CalculatorHistoryState historyState);
@Nonnull
CalculatorHistoryState addSavedState(@Nonnull CalculatorHistoryState historyState);
@Nonnull
List<CalculatorHistoryState> getStates();
@Nonnull
List<CalculatorHistoryState> getStates();
@Nonnull
List<CalculatorHistoryState> getStates(boolean includeIntermediateStates);
@Nonnull
List<CalculatorHistoryState> getStates(boolean includeIntermediateStates);
}

View File

@@ -22,10 +22,16 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.Calculator;
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorChangeEventData;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventHolder;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorUtils;
import org.solovyev.android.calculator.Locator;
import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.history.HistoryHelper;
import org.solovyev.common.history.SimpleHistoryHelper;
@@ -36,7 +42,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static org.solovyev.android.calculator.CalculatorEventType.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested;
/**
* User: Solovyev_S
@@ -45,237 +56,237 @@ import static org.solovyev.android.calculator.CalculatorEventType.*;
*/
public class CalculatorHistoryImpl implements CalculatorHistory {
private final AtomicInteger counter = new AtomicInteger(0);
private final AtomicInteger counter = new AtomicInteger(0);
@Nonnull
private final HistoryHelper<CalculatorHistoryState> history = SimpleHistoryHelper.newInstance();
@Nonnull
private final HistoryHelper<CalculatorHistoryState> history = SimpleHistoryHelper.newInstance();
@Nonnull
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
@Nonnull
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
@Nonnull
private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
@Nonnull
private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
@Nullable
private volatile CalculatorEditorViewState lastEditorViewState;
@Nullable
private volatile CalculatorEditorViewState lastEditorViewState;
public CalculatorHistoryImpl(@Nonnull Calculator calculator) {
calculator.addCalculatorEventListener(this);
}
public CalculatorHistoryImpl(@Nonnull Calculator calculator) {
calculator.addCalculatorEventListener(this);
}
@Override
public boolean isEmpty() {
synchronized (history) {
return this.history.isEmpty();
}
}
@Override
public boolean isEmpty() {
synchronized (history) {
return this.history.isEmpty();
}
}
@Override
public CalculatorHistoryState getLastHistoryState() {
synchronized (history) {
return this.history.getLastHistoryState();
}
}
@Override
public CalculatorHistoryState getLastHistoryState() {
synchronized (history) {
return this.history.getLastHistoryState();
}
}
@Override
public boolean isUndoAvailable() {
synchronized (history) {
return history.isUndoAvailable();
}
}
@Override
public boolean isUndoAvailable() {
synchronized (history) {
return history.isUndoAvailable();
}
}
@Override
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.undo(currentState);
}
}
@Override
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.undo(currentState);
}
}
@Override
public boolean isRedoAvailable() {
return history.isRedoAvailable();
}
@Override
public boolean isRedoAvailable() {
return history.isRedoAvailable();
}
@Override
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.redo(currentState);
}
}
@Override
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.redo(currentState);
}
}
@Override
public boolean isActionAvailable(@Nonnull HistoryAction historyAction) {
synchronized (history) {
return history.isActionAvailable(historyAction);
}
}
@Override
public boolean isActionAvailable(@Nonnull HistoryAction historyAction) {
synchronized (history) {
return history.isActionAvailable(historyAction);
}
}
@Override
public CalculatorHistoryState doAction(@Nonnull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.doAction(historyAction, currentState);
}
}
@Override
public CalculatorHistoryState doAction(@Nonnull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
synchronized (history) {
return history.doAction(historyAction, currentState);
}
}
@Override
public void addState(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
history.addState(currentState);
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
}
}
@Override
public void addState(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
history.addState(currentState);
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
}
}
@Nonnull
@Override
public List<CalculatorHistoryState> getStates() {
synchronized (history) {
return history.getStates();
}
}
@Nonnull
@Override
public List<CalculatorHistoryState> getStates() {
synchronized (history) {
return history.getStates();
}
}
@Nonnull
@Override
public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
synchronized (history) {
if (includeIntermediateStates) {
return getStates();
} else {
final List<CalculatorHistoryState> states = getStates();
@Nonnull
@Override
public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
synchronized (history) {
if (includeIntermediateStates) {
return getStates();
} else {
final List<CalculatorHistoryState> states = getStates();
final List<CalculatorHistoryState> result = new LinkedList<CalculatorHistoryState>();
final List<CalculatorHistoryState> result = new LinkedList<CalculatorHistoryState>();
CalculatorHistoryState laterState = null;
for (CalculatorHistoryState state : org.solovyev.common.collections.Collections.reversed(states)) {
if (laterState != null) {
final String laterEditorText = laterState.getEditorState().getText();
final String editorText = state.getEditorState().getText();
if (laterEditorText != null && editorText != null && isIntermediate(laterEditorText, editorText)) {
// intermediate result => skip from add
} else {
result.add(0, state);
}
} else {
result.add(0, state);
}
CalculatorHistoryState laterState = null;
for (CalculatorHistoryState state : org.solovyev.common.collections.Collections.reversed(states)) {
if (laterState != null) {
final String laterEditorText = laterState.getEditorState().getText();
final String editorText = state.getEditorState().getText();
if (laterEditorText != null && editorText != null && isIntermediate(laterEditorText, editorText)) {
// intermediate result => skip from add
} else {
result.add(0, state);
}
} else {
result.add(0, state);
}
laterState = state;
}
laterState = state;
}
return result;
}
}
}
return result;
}
}
}
private boolean isIntermediate(@Nonnull String laterEditorText,
@Nonnull String editorText) {
if (Math.abs(laterEditorText.length() - editorText.length()) <= 1) {
if (laterEditorText.length() > editorText.length()) {
return laterEditorText.startsWith(editorText);
} else {
return editorText.startsWith(laterEditorText);
}
}
private boolean isIntermediate(@Nonnull String laterEditorText,
@Nonnull String editorText) {
if (Math.abs(laterEditorText.length() - editorText.length()) <= 1) {
if (laterEditorText.length() > editorText.length()) {
return laterEditorText.startsWith(editorText);
} else {
return editorText.startsWith(laterEditorText);
}
}
return false;
}
return false;
}
@Override
public void clear() {
synchronized (history) {
this.history.clear();
}
}
@Override
public void clear() {
synchronized (history) {
this.history.clear();
}
}
@Override
@Nonnull
public List<CalculatorHistoryState> getSavedHistory() {
return Collections.unmodifiableList(savedHistory);
}
@Override
@Nonnull
public List<CalculatorHistoryState> getSavedHistory() {
return Collections.unmodifiableList(savedHistory);
}
@Override
@Nonnull
public CalculatorHistoryState addSavedState(@Nonnull CalculatorHistoryState historyState) {
if (historyState.isSaved()) {
return historyState;
} else {
final CalculatorHistoryState savedState = historyState.clone();
@Override
@Nonnull
public CalculatorHistoryState addSavedState(@Nonnull CalculatorHistoryState historyState) {
if (historyState.isSaved()) {
return historyState;
} else {
final CalculatorHistoryState savedState = historyState.clone();
savedState.setId(counter.incrementAndGet());
savedState.setSaved(true);
savedState.setId(counter.incrementAndGet());
savedState.setSaved(true);
savedHistory.add(savedState);
savedHistory.add(savedState);
return savedState;
}
}
return savedState;
}
}
@Override
public void load() {
// todo serso: create saved/loader class
}
@Override
public void load() {
// todo serso: create saved/loader class
}
@Override
public void save() {
// todo serso: create saved/loader class
}
@Override
public void save() {
// todo serso: create saved/loader class
}
@Override
public void fromXml(@Nonnull String xml) {
clearSavedHistory();
@Override
public void fromXml(@Nonnull String xml) {
clearSavedHistory();
HistoryUtils.fromXml(xml, this.savedHistory);
for (CalculatorHistoryState historyState : savedHistory) {
historyState.setSaved(true);
historyState.setId(counter.incrementAndGet());
}
}
HistoryUtils.fromXml(xml, this.savedHistory);
for (CalculatorHistoryState historyState : savedHistory) {
historyState.setSaved(true);
historyState.setId(counter.incrementAndGet());
}
}
@Override
public String toXml() {
return HistoryUtils.toXml(this.savedHistory);
}
@Override
public String toXml() {
return HistoryUtils.toXml(this.savedHistory);
}
@Override
public void clearSavedHistory() {
this.savedHistory.clear();
}
@Override
public void clearSavedHistory() {
this.savedHistory.clear();
}
@Override
public void removeSavedHistory(@Nonnull CalculatorHistoryState historyState) {
this.savedHistory.remove(historyState);
}
@Override
public void removeSavedHistory(@Nonnull CalculatorHistoryState historyState) {
this.savedHistory.remove(historyState);
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) {
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) {
final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData);
final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData);
if (result.isNewAfter() && result.isNewSameOrAfterSequence()) {
switch (calculatorEventType) {
case manual_calculation_requested:
lastEditorViewState = (CalculatorEditorViewState) data;
break;
case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
lastEditorViewState = editorChangeData.getNewValue();
break;
case display_state_changed:
if (result.isSameSequence()) {
if (lastEditorViewState != null) {
final CalculatorEditorViewState editorViewState = lastEditorViewState;
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState));
}
} else {
lastEditorViewState = null;
}
break;
}
}
}
}
if (result.isNewAfter() && result.isNewSameOrAfterSequence()) {
switch (calculatorEventType) {
case manual_calculation_requested:
lastEditorViewState = (CalculatorEditorViewState) data;
break;
case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
lastEditorViewState = editorChangeData.getNewValue();
break;
case display_state_changed:
if (result.isSameSequence()) {
if (lastEditorViewState != null) {
final CalculatorEditorViewState editorViewState = lastEditorViewState;
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState));
}
} else {
lastEditorViewState = null;
}
break;
}
}
}
}
}

View File

@@ -22,8 +22,6 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nonnull;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplay;
@@ -31,6 +29,8 @@ import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/11/11
@@ -40,105 +40,105 @@ import org.solovyev.android.calculator.CalculatorEditorViewState;
@Root
public class CalculatorHistoryState extends AbstractHistoryState {
@Element
@Nonnull
private EditorHistoryState editorState;
@Element
@Nonnull
private EditorHistoryState editorState;
@Element
@Nonnull
private CalculatorDisplayHistoryState displayState;
@Element
@Nonnull
private CalculatorDisplayHistoryState displayState;
private CalculatorHistoryState() {
// for xml
}
private CalculatorHistoryState() {
// for xml
}
private CalculatorHistoryState(@Nonnull EditorHistoryState editorState,
@Nonnull CalculatorDisplayHistoryState displayState) {
this.editorState = editorState;
this.displayState = displayState;
}
private CalculatorHistoryState(@Nonnull EditorHistoryState editorState,
@Nonnull CalculatorDisplayHistoryState displayState) {
this.editorState = editorState;
this.displayState = displayState;
}
@Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditor editor,
@Nonnull CalculatorDisplay display) {
final CalculatorEditorViewState editorViewState = editor.getViewState();
final CalculatorDisplayViewState displayViewState = display.getViewState();
@Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditor editor,
@Nonnull CalculatorDisplay display) {
final CalculatorEditorViewState editorViewState = editor.getViewState();
final CalculatorDisplayViewState displayViewState = display.getViewState();
return newInstance(editorViewState, displayViewState);
}
return newInstance(editorViewState, displayViewState);
}
@Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditorViewState editorViewState,
@Nonnull CalculatorDisplayViewState displayViewState) {
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editorViewState);
@Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditorViewState editorViewState,
@Nonnull CalculatorDisplayViewState displayViewState) {
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editorViewState);
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(displayViewState);
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(displayViewState);
return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
}
return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
}
@Nonnull
public EditorHistoryState getEditorState() {
return editorState;
}
@Nonnull
public EditorHistoryState getEditorState() {
return editorState;
}
public void setEditorState(@Nonnull EditorHistoryState editorState) {
this.editorState = editorState;
}
public void setEditorState(@Nonnull EditorHistoryState editorState) {
this.editorState = editorState;
}
@Nonnull
public CalculatorDisplayHistoryState getDisplayState() {
return displayState;
}
@Nonnull
public CalculatorDisplayHistoryState getDisplayState() {
return displayState;
}
public void setDisplayState(@Nonnull CalculatorDisplayHistoryState displayState) {
this.displayState = displayState;
}
public void setDisplayState(@Nonnull CalculatorDisplayHistoryState displayState) {
this.displayState = displayState;
}
@Override
public String toString() {
return "CalculatorHistoryState{" +
"editorState=" + editorState +
", displayState=" + displayState +
'}';
}
@Override
public String toString() {
return "CalculatorHistoryState{" +
"editorState=" + editorState +
", displayState=" + displayState +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CalculatorHistoryState that = (CalculatorHistoryState) o;
CalculatorHistoryState that = (CalculatorHistoryState) o;
if (this.isSaved() != that.isSaved()) return false;
if (this.getId() != that.getId()) return false;
if (!displayState.equals(that.displayState)) return false;
if (!editorState.equals(that.editorState)) return false;
if (this.isSaved() != that.isSaved()) return false;
if (this.getId() != that.getId()) return false;
if (!displayState.equals(that.displayState)) return false;
if (!editorState.equals(that.editorState)) return false;
return true;
}
return true;
}
@Override
public int hashCode() {
int result = Boolean.valueOf(isSaved()).hashCode();
result = 31 * result + getId();
result = 31 * result + editorState.hashCode();
result = 31 * result + displayState.hashCode();
return result;
}
@Override
public int hashCode() {
int result = Boolean.valueOf(isSaved()).hashCode();
result = 31 * result + getId();
result = 31 * result + editorState.hashCode();
result = 31 * result + displayState.hashCode();
return result;
}
public void setValuesFromHistory(@Nonnull CalculatorEditor editor, @Nonnull CalculatorDisplay display) {
this.getEditorState().setValuesFromHistory(editor);
this.getDisplayState().setValuesFromHistory(display);
}
public void setValuesFromHistory(@Nonnull CalculatorEditor editor, @Nonnull CalculatorDisplay display) {
this.getEditorState().setValuesFromHistory(editor);
this.getDisplayState().setValuesFromHistory(display);
}
@Override
protected CalculatorHistoryState clone() {
final CalculatorHistoryState clone = (CalculatorHistoryState) super.clone();
@Override
protected CalculatorHistoryState clone() {
final CalculatorHistoryState clone = (CalculatorHistoryState) super.clone();
clone.editorState = this.editorState.clone();
clone.displayState = this.displayState.clone();
clone.editorState = this.editorState.clone();
clone.displayState = this.displayState.clone();
return clone;
}
return clone;
}
}

View File

@@ -22,9 +22,6 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
@@ -32,88 +29,91 @@ import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@Root
public class EditorHistoryState implements Cloneable {
@Element
private int cursorPosition;
@Element
private int cursorPosition;
@Element(required = false)
@Nullable
private String text = "";
@Element(required = false)
@Nullable
private String text = "";
private EditorHistoryState() {
// for xml
}
private EditorHistoryState() {
// for xml
}
@Nonnull
public static EditorHistoryState newInstance(@Nonnull CalculatorEditorViewState viewState) {
final EditorHistoryState result = new EditorHistoryState();
@Nonnull
public static EditorHistoryState newInstance(@Nonnull CalculatorEditorViewState viewState) {
final EditorHistoryState result = new EditorHistoryState();
result.text = String.valueOf(viewState.getText());
result.cursorPosition = viewState.getSelection();
result.text = String.valueOf(viewState.getText());
result.cursorPosition = viewState.getSelection();
return result;
}
return result;
}
@Nonnull
public static EditorHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
final EditorHistoryState result = new EditorHistoryState();
@Nonnull
public static EditorHistoryState newInstance(@Nonnull CalculatorDisplayViewState viewState) {
final EditorHistoryState result = new EditorHistoryState();
result.text = viewState.getText();
result.cursorPosition = viewState.getSelection();
result.text = viewState.getText();
result.cursorPosition = viewState.getSelection();
return result;
}
return result;
}
public void setValuesFromHistory(@Nonnull CalculatorEditor editor) {
editor.setText(Strings.getNotEmpty(this.getText(), ""));
editor.setSelection(this.getCursorPosition());
}
public void setValuesFromHistory(@Nonnull CalculatorEditor editor) {
editor.setText(Strings.getNotEmpty(this.getText(), ""));
editor.setSelection(this.getCursorPosition());
}
@Nullable
public String getText() {
return text;
}
@Nullable
public String getText() {
return text;
}
public int getCursorPosition() {
return cursorPosition;
}
public int getCursorPosition() {
return cursorPosition;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EditorHistoryState)) return false;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EditorHistoryState)) return false;
EditorHistoryState that = (EditorHistoryState) o;
EditorHistoryState that = (EditorHistoryState) o;
if (cursorPosition != that.cursorPosition) return false;
if (text != null ? !text.equals(that.text) : that.text != null) return false;
if (cursorPosition != that.cursorPosition) return false;
if (text != null ? !text.equals(that.text) : that.text != null) return false;
return true;
}
return true;
}
@Override
public int hashCode() {
int result = cursorPosition;
result = 31 * result + (text != null ? text.hashCode() : 0);
return result;
}
@Override
public int hashCode() {
int result = cursorPosition;
result = 31 * result + (text != null ? text.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "EditorHistoryState{" +
"cursorPosition=" + cursorPosition +
", text='" + text + '\'' +
'}';
}
@Override
public String toString() {
return "EditorHistoryState{" +
"cursorPosition=" + cursorPosition +
", text='" + text + '\'' +
'}';
}
@Override
protected EditorHistoryState clone() {
try {
return (EditorHistoryState) super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
}
@Override
protected EditorHistoryState clone() {
try {
return (EditorHistoryState) super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
}
}

View File

@@ -37,13 +37,13 @@ import java.util.List;
@Root
public class History {
@ElementList(type = CalculatorHistoryState.class)
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
@ElementList(type = CalculatorHistoryState.class)
private List<CalculatorHistoryState> historyItems = new ArrayList<CalculatorHistoryState>();
public History() {
}
public History() {
}
public List<CalculatorHistoryState> getHistoryItems() {
return historyItems;
}
public List<CalculatorHistoryState> getHistoryItems() {
return historyItems;
}
}

View File

@@ -22,15 +22,15 @@
package org.solovyev.android.calculator.history;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.StringWriter;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/17/11
@@ -38,41 +38,41 @@ import java.util.List;
*/
class HistoryUtils {
// not intended for instantiation
private HistoryUtils() {
throw new AssertionError();
}
// not intended for instantiation
private HistoryUtils() {
throw new AssertionError();
}
public static void fromXml(@Nullable String xml, @Nonnull List<CalculatorHistoryState> historyItems) {
if (xml != null) {
final Serializer serializer = new Persister();
try {
final History history = serializer.read(History.class, xml);
for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
historyItems.add(historyItem);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public static void fromXml(@Nullable String xml, @Nonnull List<CalculatorHistoryState> historyItems) {
if (xml != null) {
final Serializer serializer = new Persister();
try {
final History history = serializer.read(History.class, xml);
for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
historyItems.add(historyItem);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Nonnull
public static String toXml(@Nonnull List<CalculatorHistoryState> historyItems) {
final History history = new History();
for (CalculatorHistoryState historyState : historyItems) {
if (historyState.isSaved()) {
history.getHistoryItems().add(historyState);
}
}
@Nonnull
public static String toXml(@Nonnull List<CalculatorHistoryState> historyItems) {
final History history = new History();
for (CalculatorHistoryState historyState : historyItems) {
if (historyState.isSaved()) {
history.getHistoryItems().add(historyState);
}
}
final StringWriter xml = new StringWriter();
final Serializer serializer = new Persister();
try {
serializer.write(history, xml);
} catch (Exception e) {
throw new RuntimeException(e);
}
return xml.toString();
}
final StringWriter xml = new StringWriter();
final Serializer serializer = new Persister();
try {
serializer.write(history, xml);
} catch (Exception e) {
throw new RuntimeException(e);
}
return xml.toString();
}
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator.jscl;
import jscl.math.Generic;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.text.TextProcessor;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.text.TextProcessor;
import jscl.math.Generic;
/**
* User: serso
@@ -36,11 +36,11 @@ import org.solovyev.android.calculator.text.TextProcessor;
*/
class FromJsclNumericTextProcessor implements TextProcessor<String, Generic> {
public static final FromJsclNumericTextProcessor instance = new FromJsclNumericTextProcessor();
public static final FromJsclNumericTextProcessor instance = new FromJsclNumericTextProcessor();
@Nonnull
@Override
public String process(@Nonnull Generic numeric) throws CalculatorParseException {
return numeric.toString().replace("*", "");
}
@Nonnull
@Override
public String process(@Nonnull Generic numeric) throws CalculatorParseException {
return numeric.toString().replace("*", "");
}
}

View File

@@ -23,67 +23,67 @@
package org.solovyev.android.calculator.jscl;
import jscl.math.Generic;
import jscl.text.ParseException;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.CalculatorMathEngine;
import org.solovyev.android.calculator.text.DummyTextProcessor;
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
import org.solovyev.android.calculator.text.TextProcessor;
import javax.annotation.Nonnull;
import jscl.math.Generic;
import jscl.text.ParseException;
public enum JsclOperation {
simplify,
elementary,
numeric;
simplify,
elementary,
numeric;
JsclOperation() {
}
JsclOperation() {
}
@Nonnull
public TextProcessor<String, Generic> getFromProcessor() {
switch (this) {
case simplify:
return FromJsclSimplifyTextProcessor.instance;
case elementary:
return DummyTextProcessor.instance;
case numeric:
return FromJsclNumericTextProcessor.instance;
default:
throw new UnsupportedOperationException();
}
}
@Nonnull
public TextProcessor<String, Generic> getFromProcessor() {
switch (this) {
case simplify:
return FromJsclSimplifyTextProcessor.instance;
case elementary:
return DummyTextProcessor.instance;
case numeric:
return FromJsclNumericTextProcessor.instance;
default:
throw new UnsupportedOperationException();
}
}
@Nonnull
public final String evaluate(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
switch (this) {
case simplify:
return engine.simplify(expression);
case elementary:
return engine.elementary(expression);
case numeric:
return engine.evaluate(expression);
default:
throw new UnsupportedOperationException();
}
}
@Nonnull
public final String evaluate(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
switch (this) {
case simplify:
return engine.simplify(expression);
case elementary:
return engine.elementary(expression);
case numeric:
return engine.evaluate(expression);
default:
throw new UnsupportedOperationException();
}
}
@Nonnull
public final Generic evaluateGeneric(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
switch (this) {
case simplify:
return engine.simplifyGeneric(expression);
case elementary:
return engine.elementaryGeneric(expression);
case numeric:
return engine.evaluateGeneric(expression);
default:
throw new UnsupportedOperationException();
}
}
@Nonnull
public final Generic evaluateGeneric(@Nonnull String expression, @Nonnull CalculatorMathEngine engine) throws ParseException {
switch (this) {
case simplify:
return engine.simplifyGeneric(expression);
case elementary:
return engine.elementaryGeneric(expression);
case numeric:
return engine.evaluateGeneric(expression);
default:
throw new UnsupportedOperationException();
}
}
}

View File

@@ -22,252 +22,219 @@
package org.solovyev.android.calculator.math;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.math.function.Constants;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.Locator;
import org.solovyev.common.JPredicate;
import org.solovyev.common.collections.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import jscl.math.function.Constants;
public enum MathType {
numeral_base(50, true, false, MathGroupType.number) {
numeral_base(50, true, false, MathGroupType.number) {
private final List<String> tokens = new ArrayList<String>(10);
{
for (NumeralBase numeralBase : NumeralBase.values()) {
tokens.add(numeralBase.getJsclPrefix());
}
}
private final List<String> tokens = new ArrayList<String>(10);
{
for (NumeralBase numeralBase : NumeralBase.values()) {
tokens.add(numeralBase.getJsclPrefix());
}
}
@Nonnull
@Override
public List<String> getTokens() {
return tokens;
}
},
@Nonnull
@Override
public List<String> getTokens() {
return tokens;
}
},
dot(200, true, true, MathGroupType.number, ".") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
}
},
dot(200, true, true, MathGroupType.number, ".") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
}
},
grouping_separator(250, false, false, MathGroupType.number, "'", " ") {
@Override
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
return i;
}
},
grouping_separator(250, false, false, MathGroupType.number, "'", " ") {
@Override
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
return i;
}
},
power_10(300, false, false, MathGroupType.number, "E"),
power_10(300, false, false, MathGroupType.number, "E"),
postfix_function(400, false, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getNames();
}
},
postfix_function(400, false, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getNames();
}
},
unary_operation(500, false, false, MathGroupType.operation, "", "-", "=") {
@Nullable
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
if (match.equals("")) {
return "-";
} else {
return null;
}
}
unary_operation(500, false, false, MathGroupType.operation, "", "-", "=") {
@Nullable
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
if (match.equals("")) {
return "-";
} else {
return null;
}
}
@Nullable
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
if (match.equals("-")) {
return "";
} else {
return null;
}
}
},
@Nullable
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
if (match.equals("-")) {
return "";
} else {
return null;
}
}
},
binary_operation(600, false, false, MathGroupType.operation, "", "-", "+", "*", "×", "", "/", "^") {
@Nullable
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
if (match.equals("-")) {
return "";
} else {
return null;
}
}
binary_operation(600, false, false, MathGroupType.operation, "", "-", "+", "*", "×", "", "/", "^") {
@Nullable
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
if (match.equals("-")) {
return "";
} else {
return null;
}
}
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
switch (match) {
case "×":
case "":
return "*";
case "":
return "-";
default:
return null;
}
}
},
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
switch (match) {
case "×":
case "":
return "*";
case "":
return "-";
default:
return null;
}
}
},
open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
}
open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator;
}
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
return "(";
}
},
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
return "(";
}
},
close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return false;
}
close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") {
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return false;
}
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
return ")";
}
},
@Override
protected String getSubstituteToJscl(@Nonnull String match) {
return ")";
}
},
function(1000, true, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getFunctionsRegistry().getNames();
}
},
function(1000, true, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getFunctionsRegistry().getNames();
}
},
operator(1050, true, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getOperatorsRegistry().getNames();
}
},
operator(1050, true, true, MathGroupType.function) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getOperatorsRegistry().getNames();
}
},
constant(1100, true, true, MathGroupType.other) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getVarsRegistry().getNames();
}
constant(1100, true, true, MathGroupType.other) {
@Nonnull
@Override
public List<String> getTokens() {
return Locator.getInstance().getEngine().getVarsRegistry().getNames();
}
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
return Constants.INF_2.getName().equals(match) ? MathType.INFINITY : super.getSubstituteFromJscl(match);
}
},
@Override
protected String getSubstituteFromJscl(@Nonnull String match) {
return Constants.INF_2.getName().equals(match) ? MathType.INFINITY : super.getSubstituteFromJscl(match);
}
},
digit(1125, true, true, MathGroupType.number) {
digit(1125, true, true, MathGroupType.number) {
private final List<String> tokens = new ArrayList<>(16);
{
for (Character character : NumeralBase.hex.getAcceptableCharacters()) {
tokens.add(character.toString());
}
}
private final List<String> tokens = new ArrayList<>(16);
{
for (Character character : NumeralBase.hex.getAcceptableCharacters()) {
tokens.add(character.toString());
}
}
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
}
@Override
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot /*&& mathTypeBefore != numeral_base*/;
}
@Nonnull
@Override
public List<String> getTokens() {
return tokens;
}
},
@Nonnull
@Override
public List<String> getTokens() {
return tokens;
}
},
comma(1150, false, false, MathGroupType.other, ","),
comma(1150, false, false, MathGroupType.other, ","),
text(1200, false, false, MathGroupType.other) {
@Override
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
text(1200, false, false, MathGroupType.other) {
@Override
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
@Override
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
};
@Override
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
};
public static enum MathGroupType {
function,
number,
operation,
other
}
@Nonnull
private final List<String> tokens;
@Nonnull
private final Integer priority;
private final boolean needMultiplicationSignBefore;
private final boolean needMultiplicationSignAfter;
@Nonnull
private final MathGroupType groupType;
MathType(@Nonnull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@Nonnull MathGroupType groupType,
@Nonnull String... tokens) {
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, Collections.asList(tokens));
}
MathType(@Nonnull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@Nonnull MathGroupType groupType,
@Nonnull List<String> tokens) {
this.priority = priority;
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
this.groupType = groupType;
this.tokens = java.util.Collections.unmodifiableList(tokens);
}
@Nonnull
public MathGroupType getGroupType() {
return groupType;
}
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
public final static Character POWER_10 = 'E';
public static final String IMAGINARY_NUMBER = "i";
public static final String IMAGINARY_NUMBER_JSCL = "√(-1)";
public static final String PI = "π";
public static final String E = "e";
public static final String C = "c";
public static final Double C_VALUE = 299792458d;
public static final String G = "G";
/* public static int getPostfixFunctionStart(@Nonnull CharSequence s, int position) throws ParseException {
assert s.length() > position;
assert s.length() > position;
int numberOfOpenGroups = 0;
int result = position;
@@ -315,207 +282,227 @@ public enum MathType {
return false;
}*/
public static final Double G_VALUE = 6.6738480E-11;
public static final String H_REDUCED = "h";
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / (2 * Math.PI);
public final static String NAN = "NaN";
public final static String INFINITY = "";
public final static String INFINITY_JSCL = "Infinity";
private static List<MathType> mathTypesByPriority;
@Nonnull
private final List<String> tokens;
@Nonnull
private final Integer priority;
private final boolean needMultiplicationSignBefore;
private final boolean needMultiplicationSignAfter;
@Nonnull
private final MathGroupType groupType;
MathType(@Nonnull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@Nonnull MathGroupType groupType,
@Nonnull String... tokens) {
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, Collections.asList(tokens));
}
@Nonnull
public List<String> getTokens() {
return tokens;
}
MathType(@Nonnull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@Nonnull MathGroupType groupType,
@Nonnull List<String> tokens) {
this.priority = priority;
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
this.groupType = groupType;
this.tokens = java.util.Collections.unmodifiableList(tokens);
}
private boolean isNeedMultiplicationSignBefore() {
return needMultiplicationSignBefore;
}
/**
* Method determines mathematical entity type for text substring starting from ith index
*
* @param text analyzed text
* @param i index which points to start of substring
* @param hexMode
* @return math entity type of substring starting from ith index of specified text
*/
@Nonnull
public static Result getType(@Nonnull String text, int i, boolean hexMode) {
if (i < 0) {
throw new IllegalArgumentException("I must be more or equals to 0.");
} else if (i >= text.length() && i != 0) {
throw new IllegalArgumentException("I must be less than size of text.");
} else if (i == 0 && text.length() == 0) {
return new Result(MathType.text, text);
}
private boolean isNeedMultiplicationSignAfter() {
return needMultiplicationSignAfter;
}
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
}
for (MathType mathType : getMathTypesByPriority()) {
final String s = Collections.find(mathType.getTokens(), startsWithFinder);
if (s != null) {
if (s.length() == 1) {
if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) {
final Character ch = s.charAt(0);
if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) {
return new Result(MathType.digit, s);
}
}
}
return new Result(mathType, s);
}
}
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
final String substitute = getSubstituteToJscl(match);
result.append(substitute == null ? match : substitute);
return returnI(i, match);
}
return new Result(MathType.text, text.substring(i));
}
protected int returnI(int i, @Nonnull String match) {
if (match.length() > 1) {
return i + match.length() - 1;
} else {
return i;
}
}
@Nonnull
private static List<MathType> getMathTypesByPriority() {
if (mathTypesByPriority == null) {
final List<MathType> result = Collections.asList(MathType.values());
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
final String substitute = getSubstituteFromJscl(match);
result.append(substitute == null ? match : substitute);
return returnI(i, match);
}
java.util.Collections.sort(result, new Comparator<MathType>() {
@Override
public int compare(MathType l, MathType r) {
return l.priority.compareTo(r.priority);
}
});
@Nullable
protected String getSubstituteFromJscl(@Nonnull String match) {
return null;
}
mathTypesByPriority = result;
}
@Nullable
protected String getSubstituteToJscl(@Nonnull String match) {
return null;
}
return mathTypesByPriority;
}
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
@Nonnull
public MathGroupType getGroupType() {
return groupType;
}
public final static Character POWER_10 = 'E';
@Nonnull
public List<String> getTokens() {
return tokens;
}
public static final String IMAGINARY_NUMBER = "i";
public static final String IMAGINARY_NUMBER_JSCL = "√(-1)";
private boolean isNeedMultiplicationSignBefore() {
return needMultiplicationSignBefore;
}
public static final String PI = "π";
public static final String E = "e";
public static final String C = "c";
public static final Double C_VALUE = 299792458d;
public static final String G = "G";
public static final Double G_VALUE = 6.6738480E-11;
public static final String H_REDUCED = "h";
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / (2 * Math.PI);
public final static String NAN = "NaN";
private boolean isNeedMultiplicationSignAfter() {
return needMultiplicationSignAfter;
}
public final static String INFINITY = "";
public final static String INFINITY_JSCL = "Infinity";
public boolean isNeedMultiplicationSignBefore(@Nonnull MathType mathTypeBefore) {
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
}
public int processToJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) throws CalculatorParseException {
final String substitute = getSubstituteToJscl(match);
result.append(substitute == null ? match : substitute);
return returnI(i, match);
}
/**
* Method determines mathematical entity type for text substring starting from ith index
*
* @param text analyzed text
* @param i index which points to start of substring
* @param hexMode
* @return math entity type of substring starting from ith index of specified text
*/
@Nonnull
public static Result getType(@Nonnull String text, int i, boolean hexMode) {
if (i < 0) {
throw new IllegalArgumentException("I must be more or equals to 0.");
} else if (i >= text.length() && i != 0) {
throw new IllegalArgumentException("I must be less than size of text.");
} else if (i == 0 && text.length() == 0) {
return new Result(MathType.text, text);
}
protected int returnI(int i, @Nonnull String match) {
if (match.length() > 1) {
return i + match.length() - 1;
} else {
return i;
}
}
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
public int processFromJscl(@Nonnull StringBuilder result, int i, @Nonnull String match) {
final String substitute = getSubstituteFromJscl(match);
result.append(substitute == null ? match : substitute);
return returnI(i, match);
}
for (MathType mathType : getMathTypesByPriority()) {
final String s = Collections.find(mathType.getTokens(), startsWithFinder);
if (s != null) {
if (s.length() == 1) {
if (hexMode || JsclMathEngine.getInstance().getNumeralBase() == NumeralBase.hex) {
final Character ch = s.charAt(0);
if (NumeralBase.hex.getAcceptableCharacters().contains(ch)) {
return new Result(MathType.digit, s);
}
}
}
return new Result(mathType, s);
}
}
@Nullable
protected String getSubstituteFromJscl(@Nonnull String match) {
return null;
}
return new Result(MathType.text, text.substring(i));
}
@Nullable
protected String getSubstituteToJscl(@Nonnull String match) {
return null;
}
public static enum MathGroupType {
function,
number,
operation,
other
}
private static List<MathType> mathTypesByPriority;
public static class Result {
@Nonnull
private static List<MathType> getMathTypesByPriority() {
if (mathTypesByPriority == null) {
final List<MathType> result = Collections.asList(MathType.values());
@Nonnull
private final MathType mathType;
java.util.Collections.sort(result, new Comparator<MathType>() {
@Override
public int compare(MathType l, MathType r) {
return l.priority.compareTo(r.priority);
}
});
@Nonnull
private final String match;
mathTypesByPriority = result;
}
public Result(@Nonnull MathType mathType, @Nonnull String match) {
this.mathType = mathType;
return mathTypesByPriority;
}
this.match = match;
}
public static class Result {
public int processToJscl(@Nonnull StringBuilder result, int i) throws CalculatorParseException {
return mathType.processToJscl(result, i, match);
}
@Nonnull
private final MathType mathType;
public int processFromJscl(@Nonnull StringBuilder result, int i) {
return mathType.processFromJscl(result, i, match);
}
@Nonnull
private final String match;
@Nonnull
public String getMatch() {
return match;
}
public Result(@Nonnull MathType mathType, @Nonnull String match) {
this.mathType = mathType;
@Nonnull
public MathType getMathType() {
return mathType;
}
}
this.match = match;
}
private static class EndsWithFinder implements JPredicate<String> {
public int processToJscl(@Nonnull StringBuilder result, int i) throws CalculatorParseException {
return mathType.processToJscl(result, i, match);
}
@Nonnull
private final CharSequence targetString;
private int i;
public int processFromJscl(@Nonnull StringBuilder result, int i) {
return mathType.processFromJscl(result, i, match);
}
private EndsWithFinder(@Nonnull CharSequence targetString) {
this.targetString = targetString;
}
@Nonnull
public String getMatch() {
return match;
}
@Override
public boolean apply(@Nullable String s) {
return targetString.subSequence(0, i).toString().endsWith(s);
}
@Nonnull
public MathType getMathType() {
return mathType;
}
}
public void setI(int i) {
this.i = i;
}
}
private static class EndsWithFinder implements JPredicate<String> {
private static class StartsWithFinder implements JPredicate<String> {
private int i;
@Nonnull
private final String targetString;
private int i;
@Nonnull
private final CharSequence targetString;
public StartsWithFinder(@Nonnull String targetString, int i) {
this.targetString = targetString;
this.i = i;
}
private EndsWithFinder(@Nonnull CharSequence targetString) {
this.targetString = targetString;
}
@Override
public boolean apply(@Nullable String s) {
return s != null && targetString.startsWith(s, i);
}
@Override
public boolean apply(@Nullable String s) {
return targetString.subSequence(0, i).toString().endsWith(s);
}
public void setI(int i) {
this.i = i;
}
}
private static class StartsWithFinder implements JPredicate<String> {
private int i;
@Nonnull
private final String targetString;
public StartsWithFinder(@Nonnull String targetString, int i) {
this.targetString = targetString;
this.i = i;
}
@Override
public boolean apply(@Nullable String s) {
return s != null && targetString.startsWith(s, i);
}
public void setI(int i) {
this.i = i;
}
}
public void setI(int i) {
this.i = i;
}
}
}

View File

@@ -22,11 +22,6 @@
package org.solovyev.android.calculator.model;
import jscl.math.function.IFunction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
@@ -45,6 +40,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.IFunction;
/**
* User: serso
* Date: 12/22/11
@@ -54,57 +54,57 @@ import java.util.Locale;
@Root(name = "function")
public class AFunction implements IFunction, MathPersistenceEntity, Serializable {
/*
**********************************************************************
*
* FIELDS
*
**********************************************************************
*/
@Transient
private Integer id;
/*
**********************************************************************
*
* FIELDS
*
**********************************************************************
*/
@Transient
private Integer id;
@Element
@Nonnull
private String name;
@Element
@Nonnull
private String name;
@Element(name = "body")
@Nonnull
private String content;
@Element(name = "body")
@Nonnull
private String content;
@ElementList(type = String.class)
@Nonnull
private List<String> parameterNames = new ArrayList<String>();
@ElementList(type = String.class)
@Nonnull
private List<String> parameterNames = new ArrayList<String>();
@Element
private boolean system;
@Element
private boolean system;
@Element(required = false)
@Nonnull
private String description = "";
@Element(required = false)
@Nonnull
private String description = "";
/*
**********************************************************************
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public AFunction() {
}
public AFunction() {
}
public AFunction(Integer id) {
this.id = id;
}
public AFunction(Integer id) {
this.id = id;
}
public static AFunction fromIFunction(@Nonnull IFunction function) {
final AFunction result = new AFunction();
public static AFunction fromIFunction(@Nonnull IFunction function) {
final AFunction result = new AFunction();
copy(result, function);
copy(result, function);
return result;
}
return result;
}
/*
**********************************************************************
@@ -114,40 +114,40 @@ public class AFunction implements IFunction, MathPersistenceEntity, Serializable
**********************************************************************
*/
@Override
public void copy(@Nonnull MathEntity mathEntity) {
if (mathEntity instanceof IFunction) {
copy(this, (IFunction) mathEntity);
} else {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + mathEntity.getClass());
}
}
private static void copy(@Nonnull AFunction target,
@Nonnull IFunction source) {
target.name = source.getName();
target.content = source.getContent();
target.description = Strings.getNotEmpty(source.getDescription(), "");
target.system = source.isSystem();
if (source.isIdDefined()) {
target.id = source.getId();
}
target.parameterNames = new ArrayList<String>(source.getParameterNames());
}
private static void copy(@Nonnull AFunction target,
@Nonnull IFunction source) {
target.name = source.getName();
target.content = source.getContent();
target.description = Strings.getNotEmpty(source.getDescription(), "");
target.system = source.isSystem();
if (source.isIdDefined()) {
target.id = source.getId();
}
target.parameterNames = new ArrayList<String>(source.getParameterNames());
}
@Override
public void copy(@Nonnull MathEntity mathEntity) {
if (mathEntity instanceof IFunction) {
copy(this, (IFunction) mathEntity);
} else {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + mathEntity.getClass());
}
}
@Override
public String toJava() {
return String.valueOf(this.content);
}
@Override
public String toJava() {
return String.valueOf(this.content);
}
@Override
public String toString() {
return "AFunction{" +
"name='" + name + '\'' +
", parameterNames=" + parameterNames +
", content='" + content + '\'' +
'}';
}
@Override
public String toString() {
return "AFunction{" +
"name='" + name + '\'' +
", parameterNames=" + parameterNames +
", content='" + content + '\'' +
'}';
}
/*
**********************************************************************
@@ -157,59 +157,59 @@ public class AFunction implements IFunction, MathPersistenceEntity, Serializable
**********************************************************************
*/
@Nonnull
public String getName() {
return name;
}
@Nonnull
public String getName() {
return name;
}
@Override
public boolean isSystem() {
return system;
}
public void setName(@Nonnull String name) {
this.name = name;
}
@Nonnull
@Override
public Integer getId() {
return this.id;
}
@Override
public boolean isSystem() {
return system;
}
@Override
public boolean isIdDefined() {
return this.id != null;
}
@Nonnull
@Override
public Integer getId() {
return this.id;
}
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
public void setName(@Nonnull String name) {
this.name = name;
}
@Override
public boolean isIdDefined() {
return this.id != null;
}
@Nonnull
public String getContent() {
return content;
}
@Nonnull
public String getContent() {
return content;
}
@Nonnull
@Override
public String getDescription() {
return this.description;
}
public void setContent(@Nonnull String content) {
this.content = content;
}
public void setContent(@Nonnull String content) {
this.content = content;
}
@Nonnull
@Override
public String getDescription() {
return this.description;
}
@Nonnull
public List<String> getParameterNames() {
return parameterNames;
}
@Nonnull
public List<String> getParameterNames() {
return parameterNames;
}
public void setParameterNames(@Nonnull List<String> parameterNames) {
this.parameterNames = parameterNames;
}
public void setParameterNames(@Nonnull List<String> parameterNames) {
this.parameterNames = parameterNames;
}
/*
**********************************************************************
@@ -219,135 +219,135 @@ public class AFunction implements IFunction, MathPersistenceEntity, Serializable
**********************************************************************
*/
public static class Builder implements MathEntityBuilder<AFunction> {
public static class Builder implements MathEntityBuilder<AFunction> {
@Nonnull
private String name;
@Nonnull
private String name;
@Nullable
private String value;
@Nullable
private String value;
private boolean system = false;
private boolean system = false;
@Nullable
private String description;
@Nullable
private String description;
@Nullable
private Integer id;
@Nullable
private Integer id;
@Nonnull
private List<String> parameterNames = Collections.emptyList();
@Nonnull
private List<String> parameterNames = Collections.emptyList();
public Builder() {
}
public Builder() {
}
public Builder(@Nonnull IFunction function) {
this.name = function.getName();
this.value = function.getContent();
this.system = function.isSystem();
this.description = function.getDescription();
if (function.isIdDefined()) {
this.id = function.getId();
}
this.parameterNames = new ArrayList<String>(function.getParameterNames());
}
public Builder(@Nonnull IFunction function) {
this.name = function.getName();
this.value = function.getContent();
this.system = function.isSystem();
this.description = function.getDescription();
if (function.isIdDefined()) {
this.id = function.getId();
}
this.parameterNames = new ArrayList<String>(function.getParameterNames());
}
public Builder(@Nonnull String name,
@Nonnull String value,
@Nonnull List<String> parameterNames) {
this.name = name;
this.value = value;
this.parameterNames = parameterNames;
}
public Builder(@Nonnull String name,
@Nonnull String value,
@Nonnull List<String> parameterNames) {
this.name = name;
this.value = value;
this.parameterNames = parameterNames;
}
@Nonnull
public Builder setName(@Nonnull String name) {
this.name = name;
return this;
}
@Nonnull
public Builder setName(@Nonnull String name) {
this.name = name;
return this;
}
@Nonnull
public Builder setValue(@Nullable String value) {
this.value = value;
return this;
}
@Nonnull
public Builder setValue(@Nullable String value) {
this.value = value;
return this;
}
protected Builder setSystem(boolean system) {
this.system = system;
return this;
}
protected Builder setSystem(boolean system) {
this.system = system;
return this;
}
public void setParameterNames(@Nonnull List<String> parameterNames) {
this.parameterNames = parameterNames;
}
public void setParameterNames(@Nonnull List<String> parameterNames) {
this.parameterNames = parameterNames;
}
@Nonnull
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
public AFunction create() throws AFunction.Builder.CreationException {
final AFunction result;
if (id != null) {
result = new AFunction(id);
} else {
result = new AFunction();
}
@Nonnull
public AFunction create() throws AFunction.Builder.CreationException {
final AFunction result;
if (id != null) {
result = new AFunction(id);
} else {
result = new AFunction();
}
result.name = name;
try {
result.content = Locator.getInstance().getCalculator().prepareExpression(value).toString();
} catch (CalculatorParseException e) {
throw new CreationException(e);
}
result.system = system;
result.description = Strings.getNotEmpty(description, "");
result.parameterNames = new ArrayList<String>(parameterNames);
result.name = name;
try {
result.content = Locator.getInstance().getCalculator().prepareExpression(value).toString();
} catch (CalculatorParseException e) {
throw new CreationException(e);
}
result.system = system;
result.description = Strings.getNotEmpty(description, "");
result.parameterNames = new ArrayList<String>(parameterNames);
return result;
}
return result;
}
public static class CreationException extends RuntimeException implements Message {
public static class CreationException extends RuntimeException implements Message {
@Nonnull
private final CalculatorParseException message;
@Nonnull
private final CalculatorParseException message;
public CreationException(@Nonnull CalculatorParseException cause) {
super(cause);
message = cause;
}
public CreationException(@Nonnull CalculatorParseException cause) {
super(cause);
message = cause;
}
@Nonnull
@Override
public String getMessageCode() {
return message.getMessageCode();
}
@Nonnull
@Override
public String getMessageCode() {
return message.getMessageCode();
}
@Nonnull
@Override
public List<Object> getParameters() {
return message.getParameters();
}
@Nonnull
@Override
public List<Object> getParameters() {
return message.getParameters();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return message.getMessageLevel();
}
@Nonnull
@Override
public MessageLevel getMessageLevel() {
return message.getMessageLevel();
}
@Override
@Nonnull
public String getLocalizedMessage() {
return message.getLocalizedMessage();
}
@Override
@Nonnull
public String getLocalizedMessage() {
return message.getLocalizedMessage();
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return message.getLocalizedMessage(locale);
}
}
}
@Nonnull
@Override
public String getLocalizedMessage(@Nonnull Locale locale) {
return message.getLocalizedMessage(locale);
}
}
}
}

View File

@@ -37,13 +37,13 @@ import java.util.List;
@Root
public class Functions implements MathEntityPersistenceContainer<AFunction> {
@ElementList(type = AFunction.class)
private List<AFunction> functions = new ArrayList<AFunction>();
@ElementList(type = AFunction.class)
private List<AFunction> functions = new ArrayList<AFunction>();
public Functions() {
}
public Functions() {
}
public List<AFunction> getEntities() {
return functions;
}
public List<AFunction> getEntities() {
return functions;
}
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator.model;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/22/11
@@ -35,12 +35,12 @@ import org.solovyev.common.math.MathEntity;
*/
public interface MathEntityBuilder<T extends MathEntity> extends JBuilder<T> {
@Nonnull
public MathEntityBuilder<T> setName(@Nonnull String name);
@Nonnull
public MathEntityBuilder<T> setName(@Nonnull String name);
@Nonnull
public MathEntityBuilder<T> setDescription(@Nullable String description);
@Nonnull
public MathEntityBuilder<T> setDescription(@Nullable String description);
@Nonnull
public MathEntityBuilder<T> setValue(@Nullable String value);
@Nonnull
public MathEntityBuilder<T> setValue(@Nullable String value);
}

View File

@@ -22,13 +22,6 @@
package org.solovyev.android.calculator.model;
import jscl.math.function.Constant;
import jscl.math.function.ExtendedConstant;
import jscl.math.function.IConstant;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient;
@@ -37,6 +30,13 @@ import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.Constant;
import jscl.math.function.ExtendedConstant;
import jscl.math.function.IConstant;
/**
* User: serso
* Date: 9/28/11
@@ -46,227 +46,227 @@ import org.solovyev.common.text.Strings;
@Root
public class Var implements IConstant, MathPersistenceEntity {
@Transient
private Integer id;
@Transient
private Integer id;
@Element
@Nonnull
private String name;
@Element
@Nonnull
private String name;
@Element(required = false)
@Nullable
private String value;
@Element(required = false)
@Nullable
private String value;
@Element
private boolean system;
@Element
private boolean system;
@Element(required = false)
@Nullable
private String description;
@Element(required = false)
@Nullable
private String description;
@Transient
private Constant constant;
@Transient
private Constant constant;
public static class Builder implements JBuilder<Var>, MathEntityBuilder<Var> {
private Var() {
}
@Nonnull
private String name;
private Var(@Nonnull Integer id) {
this.id = id;
}
@Nullable
private String value;
public void copy(@Nonnull MathEntity o) {
if (o instanceof IConstant) {
final IConstant that = ((IConstant) o);
this.name = that.getName();
this.value = that.getValue();
this.description = that.getDescription();
this.system = that.isSystem();
if (that.isIdDefined()) {
this.id = that.getId();
}
} else {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + o.getClass());
}
}
private boolean system = false;
@Nullable
public Double getDoubleValue() {
Double result = null;
if (value != null) {
try {
result = Double.valueOf(value);
} catch (NumberFormatException e) {
// do nothing - string is not a double
}
}
return result;
}
@Nullable
private String description;
@Nullable
public String getValue() {
return value;
}
@Nullable
private Integer id;
@Nonnull
@Override
public String toJava() {
return String.valueOf(value);
}
public Builder() {
}
public boolean isSystem() {
return system;
}
public Builder(@Nonnull Var var) {
this.name = var.name;
this.value = var.value;
this.system = var.system;
this.description = var.description;
this.id = var.id;
}
@Nonnull
@Override
public Integer getId() {
return this.id;
}
public Builder(@Nonnull IConstant iConstant) {
this.name = iConstant.getName();
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
this.value = iConstant.getValue();
@Override
public boolean isIdDefined() {
return this.id != null;
}
this.system = iConstant.isSystem();
this.description = iConstant.getDescription();
if (iConstant.isIdDefined()) {
this.id = iConstant.getId();
}
}
@Nonnull
public String getName() {
return name;
}
public Builder(@Nonnull String name, @Nonnull Double value) {
this(name, String.valueOf(value));
}
@Nonnull
@Override
public Constant getConstant() {
if (constant == null) {
constant = new Constant(this.name);
}
return constant;
}
public Builder(@Nonnull String name, @Nullable String value) {
this.name = name;
this.value = value;
}
@Nullable
public String getDescription() {
return description;
}
@Override
public boolean isDefined() {
return !Strings.isEmpty(value);
}
@Override
public String toString() {
return ExtendedConstant.toString(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Var var = (Var) o;
if (!name.equals(var.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
public static class Builder implements JBuilder<Var>, MathEntityBuilder<Var> {
@Nonnull
private String name;
@Nullable
private String value;
private boolean system = false;
@Nullable
private String description;
@Nullable
private Integer id;
public Builder() {
}
public Builder(@Nonnull Var var) {
this.name = var.name;
this.value = var.value;
this.system = var.system;
this.description = var.description;
this.id = var.id;
}
public Builder(@Nonnull IConstant iConstant) {
this.name = iConstant.getName();
this.value = iConstant.getValue();
this.system = iConstant.isSystem();
this.description = iConstant.getDescription();
if (iConstant.isIdDefined()) {
this.id = iConstant.getId();
}
}
public Builder(@Nonnull String name, @Nonnull Double value) {
this(name, String.valueOf(value));
}
public Builder(@Nonnull String name, @Nullable String value) {
this.name = name;
this.value = value;
}
@Nonnull
public Builder setName(@Nonnull String name) {
this.name = name;
return this;
}
@Nonnull
public Builder setName(@Nonnull String name) {
this.name = name;
return this;
}
@Nonnull
public Builder setValue(@Nullable String value) {
this.value = value;
return this;
}
@Nonnull
public Builder setValue(@Nullable String value) {
this.value = value;
return this;
}
protected Builder setSystem(boolean system) {
this.system = system;
return this;
}
protected Builder setSystem(boolean system) {
this.system = system;
return this;
}
@Nonnull
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
public Var create() {
final Var result;
if (id != null) {
result = new Var(id);
} else {
result = new Var();
}
@Nonnull
public Var create() {
final Var result;
if (id != null) {
result = new Var(id);
} else {
result = new Var();
}
result.name = name;
result.value = value;
result.system = system;
result.description = description;
result.name = name;
result.value = value;
result.system = system;
result.description = description;
return result;
}
}
private Var() {
}
private Var(@Nonnull Integer id) {
this.id = id;
}
public void copy(@Nonnull MathEntity o) {
if (o instanceof IConstant) {
final IConstant that = ((IConstant) o);
this.name = that.getName();
this.value = that.getValue();
this.description = that.getDescription();
this.system = that.isSystem();
if (that.isIdDefined()) {
this.id = that.getId();
}
} else {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + o.getClass());
}
}
@Nullable
public Double getDoubleValue() {
Double result = null;
if (value != null) {
try {
result = Double.valueOf(value);
} catch (NumberFormatException e) {
// do nothing - string is not a double
}
}
return result;
}
@Nullable
public String getValue() {
return value;
}
@Nonnull
@Override
public String toJava() {
return String.valueOf(value);
}
public boolean isSystem() {
return system;
}
@Nonnull
@Override
public Integer getId() {
return this.id;
}
@Override
public boolean isIdDefined() {
return this.id != null;
}
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
@Nonnull
public String getName() {
return name;
}
@Nonnull
@Override
public Constant getConstant() {
if (constant == null) {
constant = new Constant(this.name);
}
return constant;
}
@Nullable
public String getDescription() {
return description;
}
@Override
public boolean isDefined() {
return !Strings.isEmpty(value);
}
@Override
public String toString() {
return ExtendedConstant.toString(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Var var = (Var) o;
if (!name.equals(var.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
return result;
}
}
}

View File

@@ -38,13 +38,13 @@ import java.util.List;
@Root
public class Vars implements MathEntityPersistenceContainer<Var> {
@ElementList(type = Var.class)
private List<Var> vars = new ArrayList<Var>();
@ElementList(type = Var.class)
private List<Var> vars = new ArrayList<Var>();
public Vars() {
}
public Vars() {
}
public List<Var> getEntities() {
return vars;
}
public List<Var> getEntities() {
return vars;
}
}

View File

@@ -22,12 +22,12 @@
package org.solovyev.android.calculator.plot;
import jscl.math.Generic;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import jscl.math.Generic;
/**
* User: serso
@@ -36,63 +36,63 @@ import java.util.List;
*/
public interface CalculatorPlotter {
@Nonnull
PlotData getPlotData();
@Nonnull
PlotData getPlotData();
boolean addFunction(@Nonnull Generic expression);
boolean addFunction(@Nonnull Generic expression);
boolean addFunction(@Nonnull PlotFunction plotFunction);
boolean addFunction(@Nonnull PlotFunction plotFunction);
boolean addFunction(@Nonnull XyFunction xyFunction);
boolean addFunction(@Nonnull XyFunction xyFunction);
boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
boolean updateFunction(@Nonnull PlotFunction newFunction);
boolean updateFunction(@Nonnull PlotFunction newFunction);
boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
boolean removeFunction(@Nonnull PlotFunction plotFunction);
boolean removeFunction(@Nonnull PlotFunction plotFunction);
boolean removeFunction(@Nonnull XyFunction xyFunction);
boolean removeFunction(@Nonnull XyFunction xyFunction);
@Nonnull
PlotFunction pin(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction pin(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction unpin(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction unpin(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction show(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction show(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction hide(@Nonnull PlotFunction plotFunction);
@Nonnull
PlotFunction hide(@Nonnull PlotFunction plotFunction);
void clearAllFunctions();
void clearAllFunctions();
@Nullable
PlotFunction getFunctionById(@Nonnull String functionId);
@Nullable
PlotFunction getFunctionById(@Nonnull String functionId);
@Nonnull
List<PlotFunction> getFunctions();
@Nonnull
List<PlotFunction> getFunctions();
@Nonnull
List<PlotFunction> getVisibleFunctions();
@Nonnull
List<PlotFunction> getVisibleFunctions();
void plot();
void plot();
void plot(@Nonnull Generic expression);
void plot(@Nonnull Generic expression);
boolean is2dPlotPossible();
boolean is2dPlotPossible();
boolean isPlotPossibleFor(@Nonnull Generic expression);
boolean isPlotPossibleFor(@Nonnull Generic expression);
void setPlot3d(boolean plot3d);
void setPlot3d(boolean plot3d);
void removeAllUnpinned();
void removeAllUnpinned();
void setPlotImag(boolean plotImag);
void setPlotImag(boolean plotImag);
void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
}

View File

@@ -26,20 +26,20 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import jscl.math.Generic;
import jscl.math.function.Constant;
import org.solovyev.android.calculator.Calculator;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.Generic;
import jscl.math.function.Constant;
/**
* User: serso
* Date: 1/12/13
@@ -47,408 +47,408 @@ import java.util.List;
*/
public class CalculatorPlotterImpl implements CalculatorPlotter {
@Nonnull
private final List<PlotFunction> functions = new ArrayList<PlotFunction>();
@Nonnull
private final Calculator calculator;
@Nonnull
private final List<PlotFunction> functions = new ArrayList<PlotFunction>();
@Nonnull
private final Calculator calculator;
private final PlotResourceManager resourceManager = new MapPlotResourceManager();
private boolean plot3d = false;
private boolean adjustYAxis = true;
private boolean plotImag = false;
private int arity = 0;
@Nonnull
private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance();
@Nonnull
private PlotData plotData = new PlotData(Collections.<PlotFunction>emptyList(), plot3d, true, plotBoundaries);
public CalculatorPlotterImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
}
@Nonnull
@Override
public PlotData getPlotData() {
return plotData;
}
@Override
public boolean addFunction(@Nonnull Generic expression) {
final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(expression));
if (variables.size() > 2) throw new AssertionError();
final Constant xVariable;
if (variables.size() > 0) {
xVariable = variables.get(0);
} else {
xVariable = null;
}
final Constant yVariable;
if (variables.size() > 1) {
yVariable = variables.get(1);
} else {
yVariable = null;
}
final XyFunction realXyFunction = new XyFunction(expression, xVariable, yVariable, false);
final XyFunction imagXyFunction = new XyFunction(expression, xVariable, yVariable, true);
// first create plot functions with default line definitions
PlotFunction realPlotFunction = new PlotFunction(realXyFunction);
PlotFunction imagPlotFunction = new PlotFunction(imagXyFunction);
// then remove all unpinned graphs and free their line definitions
removeAllUnpinnedExcept(realPlotFunction, imagPlotFunction);
// create plot functions with freed line definitions
realPlotFunction = newPlotFunction(realXyFunction);
imagPlotFunction = newPlotFunction(imagXyFunction);
final boolean realAdded = addFunction(realPlotFunction);
final boolean imagAdded = addFunction(plotImag ? imagPlotFunction : PlotFunction.invisible(imagPlotFunction));
return imagAdded || realAdded;
}
@Nonnull
private PlotFunction newPlotFunction(@Nonnull XyFunction xyFunction) {
return new PlotFunction(xyFunction, resourceManager.generateAndRegister());
}
@Override
public boolean addFunction(@Nonnull PlotFunction plotFunction) {
synchronized (functions) {
if (!functions.contains(plotFunction)) {
resourceManager.register(plotFunction.getPlotLineDef());
functions.add(plotFunction);
onFunctionsChanged();
return true;
} else {
return false;
}
}
}
private boolean removeAllUnpinnedExcept(@Nonnull final PlotFunction... exceptFunctions) {
synchronized (functions) {
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
if (function != null && !function.isPinned()) {
for (PlotFunction exceptFunction : exceptFunctions) {
if (exceptFunction.equals(function)) {
return false;
}
}
resourceManager.unregister(function.getPlotLineDef());
return true;
} else {
return false;
}
}
});
if (changed) {
onFunctionsChanged();
}
return changed;
}
}
@Override
public void removeAllUnpinned() {
synchronized (functions) {
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
boolean removed = function != null && !function.isPinned();
if (removed) {
resourceManager.unregister(function.getPlotLineDef());
}
return removed;
}
});
if (changed) {
onFunctionsChanged();
}
}
}
@Override
public boolean removeFunction(@Nonnull PlotFunction plotFunction) {
synchronized (functions) {
boolean changed = functions.remove(plotFunction);
if (changed) {
resourceManager.unregister(plotFunction.getPlotLineDef());
onFunctionsChanged();
}
return changed;
}
}
@Override
public boolean addFunction(@Nonnull XyFunction xyFunction) {
return addFunction(newPlotFunction(xyFunction));
}
@Override
public boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
return addFunction(new PlotFunction(xyFunction, functionLineDef));
}
@Override
public boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
final PlotFunction newFunction = new PlotFunction(xyFunction, functionLineDef);
return updateFunction(newFunction);
}
@Override
public boolean updateFunction(@Nonnull PlotFunction newFunction) {
boolean changed = updateFunction0(newFunction);
if (changed) {
firePlotDataChangedEvent();
}
return changed;
}
public boolean updateFunction0(@Nonnull PlotFunction newFunction) {
boolean changed = false;
synchronized (functions) {
for (int i = 0; i < functions.size(); i++) {
final PlotFunction oldFunction = functions.get(i);
if (oldFunction.equals(newFunction)) {
resourceManager.unregister(oldFunction.getPlotLineDef());
resourceManager.register(newFunction.getPlotLineDef());
// update old function
functions.set(i, newFunction);
changed = true;
break;
}
}
}
return changed;
}
@Override
public boolean removeFunction(@Nonnull XyFunction xyFunction) {
return removeFunction(new PlotFunction(xyFunction));
}
@Nonnull
@Override
public PlotFunction pin(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.pin(plotFunction);
updateFunction0(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction unpin(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.unpin(plotFunction);
updateFunction0(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction show(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.visible(plotFunction);
updateFunction(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction hide(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.invisible(plotFunction);
updateFunction(newFunction);
return newFunction;
}
@Override
public void clearAllFunctions() {
synchronized (functions) {
resourceManager.unregisterAll();
functions.clear();
onFunctionsChanged();
}
}
@Nullable
@Override
public PlotFunction getFunctionById(@Nonnull final String functionId) {
synchronized (functions) {
return Iterables.find(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
return function != null && function.getXyFunction().getId().equals(functionId);
}
}, null);
}
}
// NOTE: this method must be called from synchronized block
private void onFunctionsChanged() {
if (!Thread.holdsLock(functions)) throw new AssertionError();
int maxArity = 0;
for (PlotFunction function : functions) {
final XyFunction xyFunction = function.getXyFunction();
maxArity = Math.max(maxArity, xyFunction.getArity());
}
if (maxArity > 1) {
plot3d = true;
} else {
plot3d = false;
}
if (functions.isEmpty()) {
// no functions => new plot => default boundaries
this.plotBoundaries = PlotBoundaries.newDefaultInstance();
this.adjustYAxis = true;
}
arity = maxArity;
firePlotDataChangedEvent();
}
@Nonnull
@Override
public List<PlotFunction> getFunctions() {
synchronized (functions) {
return new ArrayList<PlotFunction>(functions);
}
}
@Nonnull
@Override
public List<PlotFunction> getVisibleFunctions() {
synchronized (functions) {
return Lists.newArrayList(Iterables.filter(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
return function != null && function.isVisible();
}
}));
}
}
@Override
public void plot() {
calculator.fireCalculatorEvent(CalculatorEventType.plot_graph, null);
}
@Override
public void plot(@Nonnull Generic expression) {
addFunction(expression);
plot();
}
@Override
public boolean is2dPlotPossible() {
return arity < 2;
}
@Override
public boolean isPlotPossibleFor(@Nonnull Generic expression) {
boolean result = false;
int size = CalculatorUtils.getNotSystemConstants(expression).size();
if (size == 0 || size == 1 || size == 2) {
result = true;
}
return result;
}
@Override
public void setPlot3d(boolean plot3d) {
if (this.plot3d != plot3d) {
this.plot3d = plot3d;
firePlotDataChangedEvent();
}
}
private void firePlotDataChangedEvent() {
updatePlotData();
calculator.fireCalculatorEvent(CalculatorEventType.plot_data_changed, plotData);
}
private void updatePlotData() {
plotData = new PlotData(getVisibleFunctions(), plot3d, adjustYAxis, plotBoundaries);
}
@Override
public void setPlotImag(boolean plotImag) {
if (this.plotImag != plotImag) {
this.plotImag = plotImag;
if (toggleImagFunctions(this.plotImag)) {
firePlotDataChangedEvent();
}
}
}
@Override
public void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
if (!this.plotBoundaries.equals(plotBoundaries)) {
this.plotBoundaries = plotBoundaries;
this.adjustYAxis = false;
updatePlotData();
}
}
@Override
public void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
if (!this.plotBoundaries.equals(plotBoundaries)) {
this.plotBoundaries = plotBoundaries;
this.adjustYAxis = false;
firePlotDataChangedEvent();
}
}
private boolean toggleImagFunctions(boolean show) {
boolean changed = false;
synchronized (functions) {
for (int i = 0; i < functions.size(); i++) {
final PlotFunction plotFunction = functions.get(i);
if (plotFunction.getXyFunction().isImag()) {
functions.set(i, show ? PlotFunction.visible(plotFunction) : PlotFunction.invisible(plotFunction));
changed = true;
}
}
}
return changed;
}
private final PlotResourceManager resourceManager = new MapPlotResourceManager();
private boolean plot3d = false;
private boolean adjustYAxis = true;
private boolean plotImag = false;
private int arity = 0;
@Nonnull
private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance();
@Nonnull
private PlotData plotData = new PlotData(Collections.<PlotFunction>emptyList(), plot3d, true, plotBoundaries);
public CalculatorPlotterImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
}
@Nonnull
@Override
public PlotData getPlotData() {
return plotData;
}
@Override
public boolean addFunction(@Nonnull Generic expression) {
final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(expression));
if (variables.size() > 2) throw new AssertionError();
final Constant xVariable;
if (variables.size() > 0) {
xVariable = variables.get(0);
} else {
xVariable = null;
}
final Constant yVariable;
if (variables.size() > 1) {
yVariable = variables.get(1);
} else {
yVariable = null;
}
final XyFunction realXyFunction = new XyFunction(expression, xVariable, yVariable, false);
final XyFunction imagXyFunction = new XyFunction(expression, xVariable, yVariable, true);
// first create plot functions with default line definitions
PlotFunction realPlotFunction = new PlotFunction(realXyFunction);
PlotFunction imagPlotFunction = new PlotFunction(imagXyFunction);
// then remove all unpinned graphs and free their line definitions
removeAllUnpinnedExcept(realPlotFunction, imagPlotFunction);
// create plot functions with freed line definitions
realPlotFunction = newPlotFunction(realXyFunction);
imagPlotFunction = newPlotFunction(imagXyFunction);
final boolean realAdded = addFunction(realPlotFunction);
final boolean imagAdded = addFunction(plotImag ? imagPlotFunction : PlotFunction.invisible(imagPlotFunction));
return imagAdded || realAdded;
}
@Nonnull
private PlotFunction newPlotFunction(@Nonnull XyFunction xyFunction) {
return new PlotFunction(xyFunction, resourceManager.generateAndRegister());
}
@Override
public boolean addFunction(@Nonnull PlotFunction plotFunction) {
synchronized (functions) {
if (!functions.contains(plotFunction)) {
resourceManager.register(plotFunction.getPlotLineDef());
functions.add(plotFunction);
onFunctionsChanged();
return true;
} else {
return false;
}
}
}
private boolean removeAllUnpinnedExcept(@Nonnull final PlotFunction... exceptFunctions) {
synchronized (functions) {
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
if (function != null && !function.isPinned()) {
for (PlotFunction exceptFunction : exceptFunctions) {
if (exceptFunction.equals(function)) {
return false;
}
}
resourceManager.unregister(function.getPlotLineDef());
return true;
} else {
return false;
}
}
});
if (changed) {
onFunctionsChanged();
}
return changed;
}
}
@Override
public void removeAllUnpinned() {
synchronized (functions) {
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
boolean removed = function != null && !function.isPinned();
if (removed) {
resourceManager.unregister(function.getPlotLineDef());
}
return removed;
}
});
if (changed) {
onFunctionsChanged();
}
}
}
@Override
public boolean removeFunction(@Nonnull PlotFunction plotFunction) {
synchronized (functions) {
boolean changed = functions.remove(plotFunction);
if (changed) {
resourceManager.unregister(plotFunction.getPlotLineDef());
onFunctionsChanged();
}
return changed;
}
}
@Override
public boolean addFunction(@Nonnull XyFunction xyFunction) {
return addFunction(newPlotFunction(xyFunction));
}
@Override
public boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
return addFunction(new PlotFunction(xyFunction, functionLineDef));
}
@Override
public boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
final PlotFunction newFunction = new PlotFunction(xyFunction, functionLineDef);
return updateFunction(newFunction);
}
@Override
public boolean updateFunction(@Nonnull PlotFunction newFunction) {
boolean changed = updateFunction0(newFunction);
if (changed) {
firePlotDataChangedEvent();
}
return changed;
}
public boolean updateFunction0(@Nonnull PlotFunction newFunction) {
boolean changed = false;
synchronized (functions) {
for (int i = 0; i < functions.size(); i++) {
final PlotFunction oldFunction = functions.get(i);
if (oldFunction.equals(newFunction)) {
resourceManager.unregister(oldFunction.getPlotLineDef());
resourceManager.register(newFunction.getPlotLineDef());
// update old function
functions.set(i, newFunction);
changed = true;
break;
}
}
}
return changed;
}
@Override
public boolean removeFunction(@Nonnull XyFunction xyFunction) {
return removeFunction(new PlotFunction(xyFunction));
}
@Nonnull
@Override
public PlotFunction pin(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.pin(plotFunction);
updateFunction0(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction unpin(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.unpin(plotFunction);
updateFunction0(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction show(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.visible(plotFunction);
updateFunction(newFunction);
return newFunction;
}
@Nonnull
@Override
public PlotFunction hide(@Nonnull PlotFunction plotFunction) {
final PlotFunction newFunction = PlotFunction.invisible(plotFunction);
updateFunction(newFunction);
return newFunction;
}
@Override
public void clearAllFunctions() {
synchronized (functions) {
resourceManager.unregisterAll();
functions.clear();
onFunctionsChanged();
}
}
@Nullable
@Override
public PlotFunction getFunctionById(@Nonnull final String functionId) {
synchronized (functions) {
return Iterables.find(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
return function != null && function.getXyFunction().getId().equals(functionId);
}
}, null);
}
}
// NOTE: this method must be called from synchronized block
private void onFunctionsChanged() {
if (!Thread.holdsLock(functions)) throw new AssertionError();
int maxArity = 0;
for (PlotFunction function : functions) {
final XyFunction xyFunction = function.getXyFunction();
maxArity = Math.max(maxArity, xyFunction.getArity());
}
if (maxArity > 1) {
plot3d = true;
} else {
plot3d = false;
}
if (functions.isEmpty()) {
// no functions => new plot => default boundaries
this.plotBoundaries = PlotBoundaries.newDefaultInstance();
this.adjustYAxis = true;
}
arity = maxArity;
firePlotDataChangedEvent();
}
@Nonnull
@Override
public List<PlotFunction> getFunctions() {
synchronized (functions) {
return new ArrayList<PlotFunction>(functions);
}
}
@Nonnull
@Override
public List<PlotFunction> getVisibleFunctions() {
synchronized (functions) {
return Lists.newArrayList(Iterables.filter(functions, new Predicate<PlotFunction>() {
@Override
public boolean apply(@Nullable PlotFunction function) {
return function != null && function.isVisible();
}
}));
}
}
@Override
public void plot() {
calculator.fireCalculatorEvent(CalculatorEventType.plot_graph, null);
}
@Override
public void plot(@Nonnull Generic expression) {
addFunction(expression);
plot();
}
@Override
public boolean is2dPlotPossible() {
return arity < 2;
}
@Override
public boolean isPlotPossibleFor(@Nonnull Generic expression) {
boolean result = false;
int size = CalculatorUtils.getNotSystemConstants(expression).size();
if (size == 0 || size == 1 || size == 2) {
result = true;
}
return result;
}
@Override
public void setPlot3d(boolean plot3d) {
if (this.plot3d != plot3d) {
this.plot3d = plot3d;
firePlotDataChangedEvent();
}
}
private void firePlotDataChangedEvent() {
updatePlotData();
calculator.fireCalculatorEvent(CalculatorEventType.plot_data_changed, plotData);
}
private void updatePlotData() {
plotData = new PlotData(getVisibleFunctions(), plot3d, adjustYAxis, plotBoundaries);
}
@Override
public void setPlotImag(boolean plotImag) {
if (this.plotImag != plotImag) {
this.plotImag = plotImag;
if (toggleImagFunctions(this.plotImag)) {
firePlotDataChangedEvent();
}
}
}
@Override
public void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
if (!this.plotBoundaries.equals(plotBoundaries)) {
this.plotBoundaries = plotBoundaries;
this.adjustYAxis = false;
updatePlotData();
}
}
@Override
public void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
if (!this.plotBoundaries.equals(plotBoundaries)) {
this.plotBoundaries = plotBoundaries;
this.adjustYAxis = false;
firePlotDataChangedEvent();
}
}
private boolean toggleImagFunctions(boolean show) {
boolean changed = false;
synchronized (functions) {
for (int i = 0; i < functions.size(); i++) {
final PlotFunction plotFunction = functions.get(i);
if (plotFunction.getXyFunction().isImag()) {
functions.set(i, show ? PlotFunction.visible(plotFunction) : PlotFunction.invisible(plotFunction));
changed = true;
}
}
}
return changed;
}
}

Some files were not shown because too many files have changed in this diff Show More