From cca775c2ac765e9043dd0bbbc72c7af2d098411d Mon Sep 17 00:00:00 2001 From: serso Date: Fri, 21 Sep 2012 10:26:45 +0400 Subject: [PATCH 1/3] Revert "Calculator display changes" This reverts commit b3cc081f47b469b0a42a04d5fecf98ed57f715a8. --- .../android/calculator/Calculator.java | 55 +- .../CalculatorEvaluationEventDataImpl.java | 116 +-- .../calculator/CalculatorEventDataId.java | 41 +- .../calculator/CalculatorEventDataIdImpl.java | 130 +-- .../calculator/CalculatorEventDataImpl.java | 114 +-- .../calculator/CalculatorEventType.java | 98 +-- .../android/calculator/CalculatorImpl.java | 500 +++++------ calculatorpp/project.properties | 39 +- .../AndroidCalculatorDisplayView.java | 551 +++++++----- .../android/calculator/CalculatorModel.java | 823 +++++++++--------- .../calculator/ConversionMenuItem.java | 63 -- .../view/UnitConverterViewBuilder.java | 483 +++++----- 12 files changed, 1485 insertions(+), 1528 deletions(-) delete mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java index 433c2163..28b2ae45 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java @@ -1,30 +1,25 @@ -package org.solovyev.android.calculator; - -import jscl.NumeralBase; -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.msg.MessageRegistry; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:38 - */ -public interface Calculator extends CalculatorEventContainer { - - @NotNull - CalculatorEventDataId createFirstEventDataId(); - - void evaluate(@NotNull JsclOperation operation, - @NotNull String expression); - - @NotNull - CalculatorEventDataId evaluate(@NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr); - - @NotNull - CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to); -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.common.msg.MessageRegistry; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:38 + */ +public interface Calculator extends CalculatorEventContainer { + + @NotNull + CalculatorEventDataId createFirstEventDataId(); + + void evaluate(@NotNull JsclOperation operation, + @NotNull String expression); + + @NotNull + CalculatorEventDataId evaluate(@NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java index 9df965a0..f40cd6cf 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java @@ -1,58 +1,58 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 10:01 PM - */ -public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData { - - @NotNull - private final CalculatorEventData calculatorEventData; - - @NotNull - private final JsclOperation operation; - - @NotNull - private final String expression; - - public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData, - @NotNull JsclOperation operation, - @NotNull String expression) { - this.calculatorEventData = calculatorEventData; - this.operation = operation; - this.expression = expression; - } - - @NotNull - @Override - public JsclOperation getOperation() { - return this.operation; - } - - @NotNull - @Override - public String getExpression() { - return this.expression; - } - - @Override - public long getEventId() { - return calculatorEventData.getEventId(); - } - - @Override - @Nullable - public Long getSequenceId() { - return calculatorEventData.getSequenceId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return calculatorEventData.isAfter(calculatorEventDataId); - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.jscl.JsclOperation; + +/** + * User: serso + * Date: 9/20/12 + * Time: 10:01 PM + */ +public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData { + + @NotNull + private final CalculatorEventData calculatorEventData; + + @NotNull + private final JsclOperation operation; + + @NotNull + private final String expression; + + public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData, + @NotNull JsclOperation operation, + @NotNull String expression) { + this.calculatorEventData = calculatorEventData; + this.operation = operation; + this.expression = expression; + } + + @NotNull + @Override + public JsclOperation getOperation() { + return this.operation; + } + + @NotNull + @Override + public String getExpression() { + return this.expression; + } + + @Override + public long getEventId() { + return calculatorEventData.getEventId(); + } + + @Override + @Nullable + public Long getCalculationId() { + return calculatorEventData.getCalculationId(); + } + + @Override + public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { + return calculatorEventData.isAfter(calculatorEventDataId); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java index 783d82d6..f77558cd 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java @@ -1,21 +1,20 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 18:18 - */ -public interface CalculatorEventDataId { - - // the higher id => the later event - long getEventId(); - - // the higher id => the later event - @Nullable - Long getSequenceId(); - - boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId); -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 18:18 + */ +public interface CalculatorEventDataId { + + // the higher id => the later event + long getEventId(); + + @Nullable + Long getCalculationId(); + + boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java index ad2e2ca9..0eb8d4a0 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java @@ -1,64 +1,66 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 18:18 - */ -class CalculatorEventDataIdImpl implements CalculatorEventDataId { - - private final long eventId; - - @Nullable - private final Long sequenceId; - - private CalculatorEventDataIdImpl(long id, @Nullable Long sequenceId) { - this.eventId = id; - this.sequenceId = sequenceId; - } - - @NotNull - static CalculatorEventDataId newInstance(long id, @Nullable Long sequenceId) { - return new CalculatorEventDataIdImpl(id, sequenceId); - } - - @Override - public long getEventId() { - return this.eventId; - } - - @Nullable - @Override - public Long getSequenceId() { - return this.sequenceId; - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return this.eventId > calculatorEventDataId.getEventId(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CalculatorEventDataIdImpl)) return false; - - CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o; - - if (eventId != that.eventId) return false; - if (sequenceId != null ? !sequenceId.equals(that.sequenceId) : that.sequenceId != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = (int) (eventId ^ (eventId >>> 32)); - result = 31 * result + (sequenceId != null ? sequenceId.hashCode() : 0); - return result; - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 18:18 + */ +class CalculatorEventDataIdImpl implements CalculatorEventDataId { + + private final long eventId; + + @Nullable + private final Long calculationId; + + private CalculatorEventDataIdImpl(long id, + @Nullable Long calculationId) { + this.eventId = id; + this.calculationId = calculationId; + } + + @NotNull + static CalculatorEventDataId newInstance(long id, + @Nullable Long calculationId) { + return new CalculatorEventDataIdImpl(id, calculationId); + } + + @Override + public long getEventId() { + return this.eventId; + } + + @Nullable + @Override + public Long getCalculationId() { + return this.calculationId; + } + + @Override + public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { + return this.eventId > calculatorEventDataId.getEventId(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CalculatorEventDataIdImpl)) return false; + + CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o; + + if (eventId != that.eventId) return false; + if (calculationId != null ? !calculationId.equals(that.calculationId) : that.calculationId != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (eventId ^ (eventId >>> 32)); + result = 31 * result + (calculationId != null ? calculationId.hashCode() : 0); + return result; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java index 34b37d2b..4f7151ce 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java @@ -1,57 +1,57 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:54 - */ -class CalculatorEventDataImpl implements CalculatorEventData { - - @NotNull - private CalculatorEventDataId calculatorEventDataId; - - private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) { - this.calculatorEventDataId = calculatorEventDataId; - } - - @NotNull - public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) { - return new CalculatorEventDataImpl(calculatorEventDataId); - } - - @Override - public long getEventId() { - return calculatorEventDataId.getEventId(); - } - - @Override - @Nullable - public Long getSequenceId() { - return calculatorEventDataId.getSequenceId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return this.calculatorEventDataId.isAfter(calculatorEventDataId); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CalculatorEventDataImpl)) return false; - - CalculatorEventDataImpl that = (CalculatorEventDataImpl) o; - - if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false; - - return true; - } - - @Override - public int hashCode() { - return calculatorEventDataId.hashCode(); - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:54 + */ +class CalculatorEventDataImpl implements CalculatorEventData { + + @NotNull + private CalculatorEventDataId calculatorEventDataId; + + private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) { + this.calculatorEventDataId = calculatorEventDataId; + } + + @NotNull + public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) { + return new CalculatorEventDataImpl(calculatorEventDataId); + } + + @Override + public long getEventId() { + return calculatorEventDataId.getEventId(); + } + + @Override + @Nullable + public Long getCalculationId() { + return calculatorEventDataId.getCalculationId(); + } + + @Override + public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { + return this.calculatorEventDataId.isAfter(calculatorEventDataId); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CalculatorEventDataImpl)) return false; + + CalculatorEventDataImpl that = (CalculatorEventDataImpl) o; + + if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false; + + return true; + } + + @Override + public int hashCode() { + return calculatorEventDataId.hashCode(); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 1fd179b6..95568893 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -1,55 +1,43 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:40 - */ -public enum CalculatorEventType { - - /* - ********************************************************************** - * - * org.solovyev.android.calculator.CalculatorEvaluationEventData - * - ********************************************************************** - */ - - // @NotNull org.solovyev.android.calculator.CalculatorInput - calculation_started, - - // @NotNull org.solovyev.android.calculator.CalculatorOutput - calculation_result, - - calculation_cancelled, - - calculation_finished, - - // @NotNull org.solovyev.android.calculator.CalculatorFailure - calculation_failed, - - /* - ********************************************************************** - * - * CONVERSION - * - ********************************************************************** - */ - conversion_started, - - // @NotNull String conversion result - conversion_finished; - - public boolean isOfType(@NotNull CalculatorEventType... types) { - for (CalculatorEventType type : types) { - if ( this == type ) { - return true; - } - } - - return false; - } - -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:40 + */ +public enum CalculatorEventType { + + /* + ********************************************************************** + * + * org.solovyev.android.calculator.CalculatorEvaluationEventData + * + ********************************************************************** + */ + + // @NotNull org.solovyev.android.calculator.CalculatorInput + calculation_started, + + // @NotNull org.solovyev.android.calculator.CalculatorOutput + calculation_result, + + calculation_cancelled, + + calculation_finished, + + // @NotNull org.solovyev.android.calculator.CalculatorFailure + calculation_failed; + + public boolean isOfType(@NotNull CalculatorEventType... types) { + for (CalculatorEventType type : types) { + if ( this == type ) { + return true; + } + } + + return false; + } + +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java index 3db62bfb..1e299d59 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java @@ -1,291 +1,209 @@ -package org.solovyev.android.calculator; - -import jscl.AbstractJsclArithmeticException; -import jscl.NumeralBase; -import jscl.NumeralBaseException; -import jscl.math.Generic; -import jscl.text.ParseInterruptedException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.common.msg.MessageRegistry; -import org.solovyev.common.msg.MessageType; -import org.solovyev.common.text.StringUtils; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; - -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicLong; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:42 - */ -public class CalculatorImpl implements Calculator { - - private static final long FIRST_ID = 0; - - @NotNull - private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); - - @NotNull - private final AtomicLong counter = new AtomicLong(FIRST_ID); - - @NotNull - private final Object lock = new Object(); - - @NotNull - private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); - - @NotNull - private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10); - - public CalculatorImpl() { - } - - @NotNull - public static String doConversion(@NotNull UnitConverter converter, - @Nullable String from, - @NotNull UnitType fromUnitType, - @NotNull UnitType toUnitType) throws ConversionException{ - final String result; - - if (StringUtils.isEmpty(from)) { - result = ""; - } else { - - String to = null; - try { - if (converter.isSupported(fromUnitType, toUnitType)) { - to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue(); - } - } catch (RuntimeException e) { - throw new ConversionException(e); - } - - result = to; - } - - return result; - } - - @NotNull - private CalculatorEventDataId nextCalculatorEventDataId() { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataIdImpl.newInstance(eventId, eventId); - } - - @NotNull - private CalculatorEventDataId nextEventDataId(@NotNull Long sequenceId) { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataIdImpl.newInstance(eventId, sequenceId); - } - - /* - ********************************************************************** - * - * CALCULATION - * - ********************************************************************** - */ - - @NotNull - @Override - public CalculatorEventDataId createFirstEventDataId() { - return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID); - } - - @Override - public void evaluate(@NotNull JsclOperation operation, - @NotNull String expression) { - evaluate(operation, expression, null); - } - - @Override - @NotNull - public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation, - @NotNull final String expression, - @Nullable final MessageRegistry mr) { - - final CalculatorEventDataId eventDataId = nextCalculatorEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, mr); - } - }); - - return eventDataId; - } - - @NotNull - @Override - public CalculatorEventDataId convert(@NotNull final Generic generic, - @NotNull final NumeralBase to) { - final CalculatorEventDataId eventDataId = nextCalculatorEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - final Long sequenceId = eventDataId.getSequenceId(); - assert sequenceId != null; - - fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null); - - final NumeralBase from = CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().getNumeralBase(); - - if (from != to) { - String fromString = generic.toString(); - if (!StringUtils.isEmpty(fromString)) { - try { - fromString = ToJsclTextProcessor.getInstance().process(fromString).getExpression(); - } catch (CalculatorParseException e) { - // ok, problems while processing occurred - } - } - - // todo serso: continue - //doConversion(AndroidNumeralBase.getConverter(), fromString, AndroidNumeralBase.valueOf(fromString), AndroidNumeralBase.valueOf(to)); - } else { - fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_finished, generic.toString()); - } - } - }); - - return eventDataId; - } - - @NotNull - private CalculatorEventData newConversionEventData(@NotNull Long sequenceId) { - return CalculatorEventDataImpl.newInstance(nextEventDataId(sequenceId)); - } - - private void evaluate(@NotNull Long sequenceId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr) { - synchronized (lock) { - - PreparedExpression preparedExpression = null; - - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); - - try { - preparedExpression = preprocessor.process(expression); - - final String jsclExpression = preparedExpression.toString(); - - try { - - final Generic result = operation.evaluateGeneric(jsclExpression); - - // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) - result.toString(); - - final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result); - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data); - - } catch (AbstractJsclArithmeticException e) { - handleException(sequenceId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression)); - } - - } 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) { - - // do nothing - we ourselves interrupt the calculations - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_cancelled, null); - - } catch (CalculatorParseException e) { - handleException(sequenceId, operation, expression, mr, preparedExpression, e); - } finally { - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_finished, null); - } - } - } - - @NotNull - private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation, - @NotNull String expression, - @NotNull Long calculationId) { - return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression); - } - - private void handleException(@NotNull Long calculationId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @Nullable PreparedExpression preparedExpression, - @NotNull CalculatorParseException parseException) { - - if (operation == JsclOperation.numeric - && preparedExpression != null - && preparedExpression.isExistsUndefinedVar()) { - - evaluate(calculationId, JsclOperation.simplify, expression, mr); - - } - - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException)); - } - - private void handleException(@NotNull Long calculationId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @NotNull CalculatorEvalException evalException) { - - if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) { - evaluate(calculationId, JsclOperation.simplify, expression, mr); - } - - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException)); - } - - /* - ********************************************************************** - * - * EVENTS - * - ********************************************************************** - */ - - @Override - public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculatorEventContainer.addCalculatorEventListener(calculatorEventListener); - } - - @Override - public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener); - } - - @Override - public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); - } - - @Override - public void fireCalculatorEvents(@NotNull List calculatorEvents) { - calculatorEventContainer.fireCalculatorEvents(calculatorEvents); - } - - public static final class ConversionException extends Exception { - private ConversionException() { - } - - private ConversionException(Throwable throwable) { - super(throwable); - } - } -} +package org.solovyev.android.calculator; + +import jscl.AbstractJsclArithmeticException; +import jscl.NumeralBaseException; +import jscl.math.Generic; +import jscl.text.ParseInterruptedException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.common.msg.MessageRegistry; +import org.solovyev.common.msg.MessageType; + +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicLong; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:42 + */ +public class CalculatorImpl implements Calculator { + + private static final long FIRST_ID = 0; + + @NotNull + private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); + + @NotNull + private final AtomicLong counter = new AtomicLong(FIRST_ID); + + @NotNull + private final Object lock = new Object(); + + @NotNull + private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); + + @NotNull + private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10); + + public CalculatorImpl() { + } + + @NotNull + private CalculatorEventDataId nextCalculatorEventDataId() { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataIdImpl.newInstance(eventId, eventId); + } + + @NotNull + private CalculatorEventDataId nextEventDataId(@NotNull Long calculationId) { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataIdImpl.newInstance(eventId, calculationId); + } + + /* + ********************************************************************** + * + * CALCULATION + * + ********************************************************************** + */ + + @NotNull + @Override + public CalculatorEventDataId createFirstEventDataId() { + return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID); + } + + @Override + public void evaluate(@NotNull JsclOperation operation, + @NotNull String expression) { + evaluate(operation, expression, null); + } + + @Override + @NotNull + public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation, + @NotNull final String expression, + @Nullable final MessageRegistry mr) { + + final CalculatorEventDataId eventDataId = nextCalculatorEventDataId(); + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + CalculatorImpl.this.evaluate(eventDataId.getCalculationId(), operation, expression, mr); + } + }); + + return eventDataId; + } + + private void evaluate(@NotNull Long calculationId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr) { + synchronized (lock) { + + PreparedExpression preparedExpression = null; + + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); + + try { + preparedExpression = preprocessor.process(expression); + + final String jsclExpression = preparedExpression.toString(); + + try { + + final Generic result = operation.evaluateGeneric(jsclExpression); + + // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) + result.toString(); + + final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result); + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_result, data); + + } catch (AbstractJsclArithmeticException e) { + handleException(calculationId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression)); + } + + } catch (ArithmeticException e) { + handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage()))); + } catch (StackOverflowError e) { + handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error))); + } catch (jscl.text.ParseException e) { + handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(e)); + } catch (ParseInterruptedException e) { + + // do nothing - we ourselves interrupt the calculations + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_cancelled, null); + + } catch (CalculatorParseException e) { + handleException(calculationId, operation, expression, mr, preparedExpression, e); + } finally { + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_finished, null); + } + } + } + + @NotNull + private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation, + @NotNull String expression, + @NotNull Long calculationId) { + return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression); + } + + private void handleException(@NotNull Long calculationId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr, + @Nullable PreparedExpression preparedExpression, + @NotNull CalculatorParseException parseException) { + + if (operation == JsclOperation.numeric + && preparedExpression != null + && preparedExpression.isExistsUndefinedVar()) { + + evaluate(calculationId, JsclOperation.simplify, expression, mr); + + } + + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException)); + } + + private void handleException(@NotNull Long calculationId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr, + @NotNull CalculatorEvalException evalException) { + + if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) { + evaluate(calculationId, JsclOperation.simplify, expression, mr); + } + + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException)); + } + + /* + ********************************************************************** + * + * EVENTS + * + ********************************************************************** + */ + + @Override + public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { + calculatorEventContainer.addCalculatorEventListener(calculatorEventListener); + } + + @Override + public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { + calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener); + } + + @Override + public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); + } + + @Override + public void fireCalculatorEvents(@NotNull List calculatorEvents) { + calculatorEventContainer.fireCalculatorEvents(calculatorEvents); + } +} diff --git a/calculatorpp/project.properties b/calculatorpp/project.properties index 1b733b09..0b0ebc4d 100644 --- a/calculatorpp/project.properties +++ b/calculatorpp/project.properties @@ -1,19 +1,20 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Project target. -target=android-15 -android.library.reference.1=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 -android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 -android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 -android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 -android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 -android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 - - +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-15 +android.library.reference.1=../calculatorpp-service +android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 +android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 +android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 +android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 +android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 +android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 + + diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java index d8db12c7..59b68e21 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java @@ -1,235 +1,316 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator; - -import android.content.Context; -import android.graphics.Color; -import android.text.Html; -import android.util.AttributeSet; -import android.util.Log; -import jscl.math.Generic; -import jscl.math.function.Constant; -import jscl.math.function.IConstant; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; -import org.solovyev.android.calculator.view.TextHighlighter; -import org.solovyev.android.menu.LabeledMenuItem; -import org.solovyev.android.view.AutoResizeTextView; -import org.solovyev.common.collections.CollectionsUtils; - -import java.util.HashSet; -import java.util.Set; - -/** - * User: serso - * Date: 9/17/11 - * Time: 10:58 PM - */ -public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { - - public static enum MenuItem implements LabeledMenuItem { - - copy(R.string.c_copy) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - CalculatorModel.copyResult(context, data); - } - }, - - convert_to_bin(R.string.convert_to_bin) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - ConversionMenuItem.convert_to_bin.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation); - } - }, - - convert_to_dec(R.string.convert_to_dec) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - ConversionMenuItem.convert_to_dec.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation); - } - }, - - convert_to_hex(R.string.convert_to_hex) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - ConversionMenuItem.convert_to_hex.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation); - } - }, - - convert(R.string.c_convert) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - final Generic result = data.getResult(); - if (result != null) { - new NumeralBaseConverterDialog(result.toString()).show(context); - } - } - - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return operation == JsclOperation.numeric && generic.getConstants().isEmpty(); - } - }, - - plot(R.string.c_plot) { - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - final Generic generic = data.getResult(); - assert generic != null; - - final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); - assert constant != null; - CalculatorActivityLauncher.plotGraph(context, generic, constant); - } - - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - boolean result = false; - - if (operation == JsclOperation.simplify) { - if (getNotSystemConstants(generic).size() == 1) { - result = true; - } - } - - return result; - } - - @NotNull - private Set getNotSystemConstants(@NotNull Generic generic) { - final Set notSystemConstants = new HashSet(); - - for (Constant constant : generic.getConstants()) { - IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName()); - if (var != null && !var.isSystem() && !var.isDefined()) { - notSystemConstants.add(constant); - } - } - - return notSystemConstants; - } - }; - - private final int captionId; - - MenuItem(int captionId) { - this.captionId = captionId; - } - - public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) { - //noinspection ConstantConditions - return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation()); - } - - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return true; - } - - @NotNull - @Override - public String getCaption(@NotNull Context context) { - return context.getString(captionId); - } - } - - @NotNull - private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance(); - - @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); - - public AndroidCalculatorDisplayView(Context context) { - super(context); - } - - public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public boolean isValid() { - return this.state.isValid(); - } - - - @Override - public void setState(@NotNull CalculatorDisplayViewState state) { - this.state = state; - if ( state.isValid() ) { - setTextColor(getResources().getColor(R.color.default_text_color)); - setText(state.getStringResult()); - } else { - setTextColor(getResources().getColor(R.color.display_error_text_color)); - setText(state.getErrorMessage()); - } - } - - @NotNull - @Override - public CalculatorDisplayViewState getState() { - return this.state; - } - - @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - } - - public synchronized void redraw() { - if (isValid()) { - String text = getText().toString(); - - Log.d(this.getClass().getName(), text); - - try { - TextHighlighter.Result result = textHighlighter.process(text); - text = result.toString(); - } catch (CalculatorParseException e) { - Log.e(this.getClass().getName(), e.getMessage(), e); - } - - Log.d(this.getClass().getName(), text); - super.setText(Html.fromHtml(text), BufferType.EDITABLE); - } - - // todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize()) - setAddEllipsis(false); - setMinTextSize(10); - resizeText(); - } - - @Override - public int getSelection() { - return this.getSelectionStart(); - } - - @Override - public void setSelection(int selection) { - // not supported by TextView - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator; + +import android.content.Context; +import android.graphics.Color; +import android.text.Html; +import android.util.AttributeSet; +import android.util.Log; +import jscl.NumeralBase; +import jscl.math.Generic; +import jscl.math.function.Constant; +import jscl.math.function.IConstant; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; +import org.solovyev.android.calculator.view.TextHighlighter; +import org.solovyev.android.calculator.view.UnitConverterViewBuilder; +import org.solovyev.android.menu.AMenuItem; +import org.solovyev.android.menu.LabeledMenuItem; +import org.solovyev.android.view.AutoResizeTextView; +import org.solovyev.common.collections.CollectionsUtils; +import org.solovyev.common.text.StringUtils; + +import java.util.HashSet; +import java.util.Set; + +/** + * User: serso + * Date: 9/17/11 + * Time: 10:58 PM + */ +public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { + + private static enum ConversionMenuItem implements AMenuItem { + convert_to_bin(NumeralBase.bin), + convert_to_dec(NumeralBase.dec), + convert_to_hex(NumeralBase.hex); + + @NotNull + private final NumeralBase toNumeralBase; + + private ConversionMenuItem(@NotNull NumeralBase toNumeralBase) { + this.toNumeralBase = toNumeralBase; + } + + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + boolean result = false; + + if (operation == JsclOperation.numeric) { + if (generic.getConstants().isEmpty()) { + try { + convert(generic); + + // conversion possible => return true + result = true; + + } catch (UnitConverterViewBuilder.ConversionException e) { + // conversion is not possible => return false + } + } + } + + return result; + } + + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase(); + + final Generic lastResult = CalculatorLocatorImpl.getInstance().getCalculatorDisplay().getViewState().getResult(); + + if (lastResult != null) { + String to; + try { + to = convert(lastResult); + + // add prefix + if (fromNumeralBase != toNumeralBase) { + to = toNumeralBase.getJsclPrefix() + to; + } + } catch (UnitConverterViewBuilder.ConversionException e) { + to = context.getString(R.string.c_error); + } + + data.setText(to); + //data.redraw(); + } + } + + @NotNull + private String convert(@NotNull Generic generic) throws UnitConverterViewBuilder.ConversionException { + final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase(); + + if (fromNumeralBase != toNumeralBase) { + String from = generic.toString(); + if (!StringUtils.isEmpty(from)) { + try { + from = ToJsclTextProcessor.getInstance().process(from).getExpression(); + } catch (CalculatorParseException e) { + // ok, problems while processing occurred + } + } + + return UnitConverterViewBuilder.doConversion(AndroidNumeralBase.getConverter(), from, AndroidNumeralBase.valueOf(fromNumeralBase), AndroidNumeralBase.valueOf(toNumeralBase)); + } else { + return generic.toString(); + } + } + } + + public static enum MenuItem implements LabeledMenuItem { + + copy(R.string.c_copy) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + CalculatorModel.copyResult(context, data); + } + }, + + convert_to_bin(R.string.convert_to_bin) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + ConversionMenuItem.convert_to_bin.onClick(data, context); + } + + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation); + } + }, + + convert_to_dec(R.string.convert_to_dec) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + ConversionMenuItem.convert_to_dec.onClick(data, context); + } + + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation); + } + }, + + convert_to_hex(R.string.convert_to_hex) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + ConversionMenuItem.convert_to_hex.onClick(data, context); + } + + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation); + } + }, + + convert(R.string.c_convert) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + final Generic result = data.getState().getResult(); + if (result != null) { + new NumeralBaseConverterDialog(result.toString()).show(context); + } + } + + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return operation == JsclOperation.numeric && generic.getConstants().isEmpty(); + } + }, + + plot(R.string.c_plot) { + @Override + public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + final Generic generic = data.getState().getResult(); + assert generic != null; + + final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); + assert constant != null; + CalculatorActivityLauncher.plotGraph(context, generic, constant); + } + + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + boolean result = false; + + if (operation == JsclOperation.simplify) { + if (getNotSystemConstants(generic).size() == 1) { + result = true; + } + } + + return result; + } + + @NotNull + private Set getNotSystemConstants(@NotNull Generic generic) { + final Set notSystemConstants = new HashSet(); + + for (Constant constant : generic.getConstants()) { + IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName()); + if (var != null && !var.isSystem() && !var.isDefined()) { + notSystemConstants.add(constant); + } + } + + return notSystemConstants; + } + }; + + private final int captionId; + + MenuItem(int captionId) { + this.captionId = captionId; + } + + public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) { + //noinspection ConstantConditions + return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation()); + } + + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return true; + } + + @NotNull + @Override + public String getCaption(@NotNull Context context) { + return context.getString(captionId); + } + } + + @NotNull + private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance(); + + @NotNull + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); + + public AndroidCalculatorDisplayView(Context context) { + super(context); + } + + public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public boolean isValid() { + return this.state.isValid(); + } + + + @Override + public void setState(@NotNull CalculatorDisplayViewState state) { + this.state = state; + if ( state.isValid() ) { + setTextColor(getResources().getColor(R.color.default_text_color)); + setText(state.getStringResult()); + } else { + setTextColor(getResources().getColor(R.color.display_error_text_color)); + setText(state.getErrorMessage()); + } + } + + @NotNull + @Override + public CalculatorDisplayViewState getState() { + return this.state; + } + + @Override + public void setText(CharSequence text, BufferType type) { + super.setText(text, type); + } + + public synchronized void redraw() { + if (isValid()) { + String text = getText().toString(); + + Log.d(this.getClass().getName(), text); + + try { + TextHighlighter.Result result = textHighlighter.process(text); + text = result.toString(); + } catch (CalculatorParseException e) { + Log.e(this.getClass().getName(), e.getMessage(), e); + } + + Log.d(this.getClass().getName(), text); + super.setText(Html.fromHtml(text), BufferType.EDITABLE); + } + + // todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize()) + setAddEllipsis(false); + setMinTextSize(10); + resizeText(); + } + + @Override + public int getSelection() { + return this.getSelectionStart(); + } + + @Override + public void setSelection(int selection) { + // not supported by TextView + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java index e43e9131..d459f15a 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java @@ -1,411 +1,412 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Handler; -import android.text.ClipboardManager; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.CursorControl; -import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.history.TextViewEditorAdapter; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.math.MathType; -import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.history.HistoryControl; -import org.solovyev.android.menu.AMenuBuilder; -import org.solovyev.android.menu.MenuImpl; -import org.solovyev.common.MutableObject; -import org.solovyev.common.history.HistoryAction; -import org.solovyev.common.msg.Message; -import org.solovyev.common.text.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * User: serso - * Date: 9/12/11 - * Time: 11:15 PM - */ -public enum CalculatorModel implements CursorControl, HistoryControl, CalculatorEngineControl { - - instance; - - // millis to wait before evaluation after user edit action - public static final int EVAL_DELAY_MILLIS = 0; - - @NotNull - private CalculatorEditor editor; - - @NotNull - private AndroidCalculatorDisplayView display; - - @NotNull - private CalculatorEngine calculatorEngine; - - public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) { - Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity); - this.calculatorEngine = calculator; - - this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor); - this.editor.init(preferences); - preferences.registerOnSharedPreferenceChangeListener(editor); - - this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay); - this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); - - final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState(); - if (lastState == null) { - saveHistoryState(); - } else { - setCurrentHistoryState(lastState); - } - - - return this; - } - - private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) { - final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); - - final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null); - ((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage); - - final AlertDialog.Builder builder = new AlertDialog.Builder(activity) - .setPositiveButton(R.string.c_cancel, null) - .setView(errorMessageView); - - builder.create().show(); - } - - public void copyResult(@NotNull Context context) { - copyResult(context, display); - } - - public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) { - if (viewState.isValid()) { - final CharSequence text = viewState.getText(); - if (!StringUtils.isEmpty(text)) { - final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(text.toString()); - Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); - } - } - } - - private void saveHistoryState() { - AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState()); - } - - public void setCursorOnStart() { - editor.setSelection(0); - } - - public void setCursorOnEnd() { - editor.setSelection(editor.getText().length()); - } - - public void moveCursorLeft() { - if (editor.getSelectionStart() > 0) { - editor.setSelection(editor.getSelectionStart() - 1); - } - } - - public void moveCursorRight() { - if (editor.getSelectionStart() < editor.getText().length()) { - editor.setSelection(editor.getSelectionStart() + 1); - } - } - - public void doTextOperation(@NotNull TextOperation operation) { - doTextOperation(operation, true); - } - - public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) { - doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false); - } - - public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) { - final String editorStateBefore = this.editor.getText().toString(); - - Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'"); - operation.doOperation(this.editor); - //Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())); - - final String editorStateAfter = this.editor.getText().toString(); - if (forceEval ||!editorStateBefore.equals(editorStateAfter)) { - - editor.redraw(); - - evaluate(delayEvaluate, editorStateAfter, jsclOperation, null); - } - } - - @NotNull - private final static MutableObject pendingOperation = new MutableObject(); - - private void evaluate(boolean delayEvaluate, - @NotNull final String expression, - @NotNull final JsclOperation operation, - @Nullable CalculatorHistoryState historyState) { - - final CalculatorHistoryState localHistoryState; - if (historyState == null) { - //this.display.setText(""); - localHistoryState = getCurrentHistoryState(); - } else { - this.display.setText(historyState.getDisplayState().getEditorState().getText()); - localHistoryState = historyState; - } - - pendingOperation.setObject(new Runnable() { - @Override - public void run() { - // allow only one runner at one time - synchronized (pendingOperation) { - //lock all operations with history - if (pendingOperation.getObject() == this) { - // actually nothing shall be logged while text operations are done - evaluate(expression, operation, this); - - if (pendingOperation.getObject() == this) { - // todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null) - pendingOperation.setObject(null); - localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState()); - } - } - } - } - }); - - if (delayEvaluate) { - if (historyState == null) { - AndroidCalculatorHistoryImpl.instance.addState(localHistoryState); - } - // todo serso: this is not correct - operation is processing still in the same thread - new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS); - } else { - pendingOperation.getObject().run(); - if (historyState == null) { - AndroidCalculatorHistoryImpl.instance.addState(localHistoryState); - } - } - } - - @Override - public void evaluate() { - evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null); - } - - public void evaluate(@NotNull JsclOperation operation) { - evaluate(false, this.editor.getText().toString(), operation, null); - } - - @Override - public void simplify() { - evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null); - } - - private void evaluate(@Nullable final String expression, - @NotNull JsclOperation operation, - @NotNull Runnable currentRunner) { - - if (!StringUtils.isEmpty(expression)) { - try { - Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/); - final CalculatorOutput result = calculatorEngine.evaluate(operation, expression); - - // todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter - if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) { - display.setText(result.getStringResult()); - } else { - display.setText(""); - } - display.setJsclOperation(result.getOperation()); - display.setGenericResult(result.getResult()); - } catch (CalculatorParseException e) { - handleEvaluationException(expression, display, operation, e); - } catch (CalculatorEvalException e) { - handleEvaluationException(expression, display, operation, e); - } - } else { - this.display.setText(""); - this.display.setJsclOperation(operation); - this.display.setGenericResult(null); - } - - - - this.display.redraw(); - } - - private void handleEvaluationException(@NotNull String expression, - @NotNull AndroidCalculatorDisplayView localDisplay, - @NotNull JsclOperation operation, - @NotNull Message e) { - Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e); - if ( StringUtils.isEmpty(localDisplay.getText()) ) { - // if previous display state was empty -> show error - localDisplay.setText(R.string.c_syntax_error); - } else { - // show previous result instead of error caption (actually previous result will be greyed) - } - localDisplay.setJsclOperation(operation); - localDisplay.setGenericResult(null); - localDisplay.setValid(false); - localDisplay.setErrorMessage(e.getLocalizedMessage()); - } - - public void clear() { - if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) { - editor.getText().clear(); - display.setText(""); - saveHistoryState(); - } - } - - public void processDigitButtonAction(@Nullable final String text) { - processDigitButtonAction(text, true); - } - - public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) { - - if (!StringUtils.isEmpty(text)) { - doTextOperation(new CalculatorModel.TextOperation() { - - @Override - public void doOperation(@NotNull EditText editor) { - 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; - } - - if (cursorPositionOffset == 0) { - if (MathType.openGroupSymbols.contains(text)) { - cursorPositionOffset = -1; - } - } - - editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString()); - editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset); - } - }, delayEvaluate); - } - } - - public static interface TextOperation { - - void doOperation(@NotNull EditText editor); - - } - - @Override - public void doHistoryAction(@NotNull HistoryAction historyAction) { - synchronized (AndroidCalculatorHistoryImpl.instance) { - if (AndroidCalculatorHistoryImpl.instance.isActionAvailable(historyAction)) { - final CalculatorHistoryState newState = AndroidCalculatorHistoryImpl.instance.doAction(historyAction, getCurrentHistoryState()); - if (newState != null) { - setCurrentHistoryState(newState); - } - } - } - } - - @Override - public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { - synchronized (AndroidCalculatorHistoryImpl.instance) { - Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState); - - editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display); - - final String expression = this.editor.getText().toString(); - if ( !StringUtils.isEmpty(expression) ) { - if ( StringUtils.isEmpty(this.display.getText().toString()) ) { - evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState); - } - } - - editor.redraw(); - display.redraw(); - } - } - - @Override - @NotNull - public CalculatorHistoryState getCurrentHistoryState() { - synchronized (AndroidCalculatorHistoryImpl.instance) { - return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display); - } - } - - @NotNull - public AndroidCalculatorDisplayView getDisplay() { - return display; - } - - private static class CalculatorDisplayOnClickListener implements View.OnClickListener { - - @NotNull - private final Activity activity; - - public CalculatorDisplayOnClickListener(@NotNull Activity activity) { - this.activity = activity; - } - - @Override - public void onClick(View v) { - if (v instanceof CalculatorDisplayView) { - final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay(); - - final CalculatorDisplayViewState displayViewState = cd.getViewState(); - - if (displayViewState.isValid()) { - final List filteredMenuItems = new ArrayList(AndroidCalculatorDisplayView.MenuItem.values().length); - for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) { - if (menuItem.isItemVisible(displayViewState)) { - filteredMenuItems.add(menuItem); - } - } - - if (!filteredMenuItems.isEmpty()) { - AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show(); - } - - } else { - final String errorMessage = displayViewState.getErrorMessage(); - if (errorMessage != null) { - showEvaluationError(activity, errorMessage); - } - } - } - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Handler; +import android.text.ClipboardManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.CursorControl; +import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.history.TextViewEditorAdapter; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.math.MathType; +import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.history.HistoryControl; +import org.solovyev.android.menu.AMenuBuilder; +import org.solovyev.android.menu.MenuImpl; +import org.solovyev.common.MutableObject; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.msg.Message; +import org.solovyev.common.text.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * User: serso + * Date: 9/12/11 + * Time: 11:15 PM + */ +public enum CalculatorModel implements CursorControl, HistoryControl, CalculatorEngineControl { + + instance; + + // millis to wait before evaluation after user edit action + public static final int EVAL_DELAY_MILLIS = 0; + + @NotNull + private CalculatorEditor editor; + + @NotNull + private AndroidCalculatorDisplayView display; + + @NotNull + private CalculatorEngine calculatorEngine; + + public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) { + Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity); + this.calculatorEngine = calculator; + + this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor); + this.editor.init(preferences); + preferences.registerOnSharedPreferenceChangeListener(editor); + + this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay); + this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); + + final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState(); + if (lastState == null) { + saveHistoryState(); + } else { + setCurrentHistoryState(lastState); + } + + + return this; + } + + private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) { + final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + + final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null); + ((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage); + + final AlertDialog.Builder builder = new AlertDialog.Builder(activity) + .setPositiveButton(R.string.c_cancel, null) + .setView(errorMessageView); + + builder.create().show(); + } + + public void copyResult(@NotNull Context context) { + copyResult(context, display); + } + + public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayView display) { + final CalculatorDisplayViewState displayViewState = display.getState(); + if (displayViewState.isValid()) { + final CharSequence text = display.getText(); + if (!StringUtils.isEmpty(text)) { + final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(text.toString()); + Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); + } + } + } + + private void saveHistoryState() { + AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState()); + } + + public void setCursorOnStart() { + editor.setSelection(0); + } + + public void setCursorOnEnd() { + editor.setSelection(editor.getText().length()); + } + + public void moveCursorLeft() { + if (editor.getSelectionStart() > 0) { + editor.setSelection(editor.getSelectionStart() - 1); + } + } + + public void moveCursorRight() { + if (editor.getSelectionStart() < editor.getText().length()) { + editor.setSelection(editor.getSelectionStart() + 1); + } + } + + public void doTextOperation(@NotNull TextOperation operation) { + doTextOperation(operation, true); + } + + public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate) { + doTextOperation(operation, delayEvaluate, JsclOperation.numeric, false); + } + + public void doTextOperation(@NotNull TextOperation operation, boolean delayEvaluate, @NotNull JsclOperation jsclOperation, boolean forceEval) { + final String editorStateBefore = this.editor.getText().toString(); + + Log.d(CalculatorModel.class.getName(), "Editor state changed before '" + editorStateBefore + "'"); + operation.doOperation(this.editor); + //Log.d(CalculatorModel.class.getName(), "Doing text operation" + StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())); + + final String editorStateAfter = this.editor.getText().toString(); + if (forceEval ||!editorStateBefore.equals(editorStateAfter)) { + + editor.redraw(); + + evaluate(delayEvaluate, editorStateAfter, jsclOperation, null); + } + } + + @NotNull + private final static MutableObject pendingOperation = new MutableObject(); + + private void evaluate(boolean delayEvaluate, + @NotNull final String expression, + @NotNull final JsclOperation operation, + @Nullable CalculatorHistoryState historyState) { + + final CalculatorHistoryState localHistoryState; + if (historyState == null) { + //this.display.setText(""); + localHistoryState = getCurrentHistoryState(); + } else { + this.display.setText(historyState.getDisplayState().getEditorState().getText()); + localHistoryState = historyState; + } + + pendingOperation.setObject(new Runnable() { + @Override + public void run() { + // allow only one runner at one time + synchronized (pendingOperation) { + //lock all operations with history + if (pendingOperation.getObject() == this) { + // actually nothing shall be logged while text operations are done + evaluate(expression, operation, this); + + if (pendingOperation.getObject() == this) { + // todo serso: of course there is small probability that someone will set pendingOperation after if statement but before .setObject(null) + pendingOperation.setObject(null); + localHistoryState.setDisplayState(getCurrentHistoryState().getDisplayState()); + } + } + } + } + }); + + if (delayEvaluate) { + if (historyState == null) { + AndroidCalculatorHistoryImpl.instance.addState(localHistoryState); + } + // todo serso: this is not correct - operation is processing still in the same thread + new Handler().postDelayed(pendingOperation.getObject(), EVAL_DELAY_MILLIS); + } else { + pendingOperation.getObject().run(); + if (historyState == null) { + AndroidCalculatorHistoryImpl.instance.addState(localHistoryState); + } + } + } + + @Override + public void evaluate() { + evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null); + } + + public void evaluate(@NotNull JsclOperation operation) { + evaluate(false, this.editor.getText().toString(), operation, null); + } + + @Override + public void simplify() { + evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null); + } + + private void evaluate(@Nullable final String expression, + @NotNull JsclOperation operation, + @NotNull Runnable currentRunner) { + + if (!StringUtils.isEmpty(expression)) { + try { + Log.d(CalculatorModel.class.getName(), "Trying to evaluate '" + operation + "': " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/); + final CalculatorOutput result = calculatorEngine.evaluate(operation, expression); + + // todo serso: second condition might replaced with expression.equals(this.editor.getText().toString()) ONLY if expression will be formatted with text highlighter + if (currentRunner == pendingOperation.getObject() && this.editor.getText().length() > 0) { + display.setText(result.getStringResult()); + } else { + display.setText(""); + } + display.setJsclOperation(result.getOperation()); + display.setGenericResult(result.getResult()); + } catch (CalculatorParseException e) { + handleEvaluationException(expression, display, operation, e); + } catch (CalculatorEvalException e) { + handleEvaluationException(expression, display, operation, e); + } + } else { + this.display.setText(""); + this.display.setJsclOperation(operation); + this.display.setGenericResult(null); + } + + + + this.display.redraw(); + } + + private void handleEvaluationException(@NotNull String expression, + @NotNull AndroidCalculatorDisplayView localDisplay, + @NotNull JsclOperation operation, + @NotNull Message e) { + Log.d(CalculatorModel.class.getName(), "Evaluation failed for : " + expression + ". Error message: " + e); + if ( StringUtils.isEmpty(localDisplay.getText()) ) { + // if previous display state was empty -> show error + localDisplay.setText(R.string.c_syntax_error); + } else { + // show previous result instead of error caption (actually previous result will be greyed) + } + localDisplay.setJsclOperation(operation); + localDisplay.setGenericResult(null); + localDisplay.setValid(false); + localDisplay.setErrorMessage(e.getLocalizedMessage()); + } + + public void clear() { + if (!StringUtils.isEmpty(editor.getText()) || !StringUtils.isEmpty(display.getText())) { + editor.getText().clear(); + display.setText(""); + saveHistoryState(); + } + } + + public void processDigitButtonAction(@Nullable final String text) { + processDigitButtonAction(text, true); + } + + public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) { + + if (!StringUtils.isEmpty(text)) { + doTextOperation(new CalculatorModel.TextOperation() { + + @Override + public void doOperation(@NotNull EditText editor) { + 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; + } + + if (cursorPositionOffset == 0) { + if (MathType.openGroupSymbols.contains(text)) { + cursorPositionOffset = -1; + } + } + + editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString()); + editor.setSelection(editor.getSelectionStart() + cursorPositionOffset, editor.getSelectionEnd() + cursorPositionOffset); + } + }, delayEvaluate); + } + } + + public static interface TextOperation { + + void doOperation(@NotNull EditText editor); + + } + + @Override + public void doHistoryAction(@NotNull HistoryAction historyAction) { + synchronized (AndroidCalculatorHistoryImpl.instance) { + if (AndroidCalculatorHistoryImpl.instance.isActionAvailable(historyAction)) { + final CalculatorHistoryState newState = AndroidCalculatorHistoryImpl.instance.doAction(historyAction, getCurrentHistoryState()); + if (newState != null) { + setCurrentHistoryState(newState); + } + } + } + } + + @Override + public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { + synchronized (AndroidCalculatorHistoryImpl.instance) { + Log.d(this.getClass().getName(), "Saved history found: " + editorHistoryState); + + editorHistoryState.setValuesFromHistory(new TextViewEditorAdapter(this.editor), this.display); + + final String expression = this.editor.getText().toString(); + if ( !StringUtils.isEmpty(expression) ) { + if ( StringUtils.isEmpty(this.display.getText().toString()) ) { + evaluate(false, expression, this.display.getJsclOperation(), editorHistoryState); + } + } + + editor.redraw(); + display.redraw(); + } + } + + @Override + @NotNull + public CalculatorHistoryState getCurrentHistoryState() { + synchronized (AndroidCalculatorHistoryImpl.instance) { + return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display); + } + } + + @NotNull + public AndroidCalculatorDisplayView getDisplay() { + return display; + } + + private static class CalculatorDisplayOnClickListener implements View.OnClickListener { + + @NotNull + private final Activity activity; + + public CalculatorDisplayOnClickListener(@NotNull Activity activity) { + this.activity = activity; + } + + @Override + public void onClick(View v) { + if (v instanceof CalculatorDisplayView) { + final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay(); + + final CalculatorDisplayViewState displayViewState = cd.getViewState(); + + if (displayViewState.isValid()) { + final List filteredMenuItems = new ArrayList(AndroidCalculatorDisplayView.MenuItem.values().length); + for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) { + if (menuItem.isItemVisible(displayViewState)) { + filteredMenuItems.add(menuItem); + } + } + + if (!filteredMenuItems.isEmpty()) { + AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show(); + } + + } else { + final String errorMessage = displayViewState.getErrorMessage(); + if (errorMessage != null) { + showEvaluationError(activity, errorMessage); + } + } + } + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java deleted file mode 100644 index c33039d8..00000000 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/ConversionMenuItem.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.solovyev.android.calculator; - -import android.content.Context; -import jscl.NumeralBase; -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.menu.AMenuItem; - -/** - * User: serso - * Date: 9/21/12 - * Time: 12:11 AM - */ -enum ConversionMenuItem implements AMenuItem { - - convert_to_bin(NumeralBase.bin), - convert_to_dec(NumeralBase.dec), - convert_to_hex(NumeralBase.hex); - - @NotNull - private final NumeralBase toNumeralBase; - - ConversionMenuItem(@NotNull NumeralBase toNumeralBase) { - this.toNumeralBase = toNumeralBase; - } - - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - boolean result = false; - - if (operation == JsclOperation.numeric) { - if (generic.getConstants().isEmpty()) { - try { - convert(generic); - - // conversion possible => return true - result = true; - - } catch (CalculatorImpl.ConversionException e) { - // conversion is not possible => return false - } - } - } - - return result; - } - - @Override - public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { - final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase(); - - final Generic lastResult = data.getResult(); - - if (lastResult != null) { - convert(lastResult); - } - } - - private void convert(@NotNull Generic generic) { - CalculatorLocatorImpl.getInstance().getCalculator().convert(generic, this.toNumeralBase); - } -} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java index 41603705..d75c7240 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java @@ -1,224 +1,259 @@ -package org.solovyev.android.calculator.view; - -import android.app.Activity; -import android.content.Context; -import android.text.ClipboardManager; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.View; -import android.view.ViewGroup; -import android.widget.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorImpl; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; -import org.solovyev.android.calculator.R; -import org.solovyev.android.view.ViewBuilder; -import org.solovyev.android.view.ViewFromLayoutBuilder; - -import java.util.Collections; -import java.util.List; - -/** - * User: serso - * Date: 4/20/12 - * Time: 4:50 PM - */ -public class UnitConverterViewBuilder implements ViewBuilder { - - @NotNull - private List> fromUnitTypes = Collections.emptyList(); - - @NotNull - private List> toUnitTypes = Collections.emptyList(); - - @Nullable - private Unit fromValue; - - @NotNull - private UnitConverter converter = UnitConverter.Dummy.getInstance(); - - @Nullable - private View.OnClickListener okButtonOnClickListener; - - @Nullable - private CustomButtonData customButtonData; - - public void setFromUnitTypes(@NotNull List> fromUnitTypes) { - this.fromUnitTypes = fromUnitTypes; - } - - public void setToUnitTypes(@NotNull List> toUnitTypes) { - this.toUnitTypes = toUnitTypes; - } - - public void setFromValue(@Nullable Unit fromValue) { - this.fromValue = fromValue; - } - - public void setConverter(@NotNull UnitConverter converter) { - this.converter = converter; - } - - public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) { - this.okButtonOnClickListener = okButtonOnClickListener; - } - - public void setCustomButtonData(@Nullable CustomButtonData customButtonData) { - this.customButtonData = customButtonData; - } - - @NotNull - @Override - public View build(@NotNull final Context context) { - final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context); - - final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); - final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); - fromEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - doConversion(main, context, UnitConverterViewBuilder.this.converter); - } - }); - - fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes); - fillSpinner(main, context, R.id.unit_types_to, toUnitTypes); - - if (fromValue != null) { - fromEditText.setText(fromValue.getValue()); - - int i = fromUnitTypes.indexOf(fromValue.getUnitType()); - if ( i >= 0 ) { - fromSpinner.setSelection(i); - } - } - - final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button); - copyButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - final EditText toEditText = (EditText) main.findViewById(R.id.units_to); - - final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(toEditText.getText().toString()); - Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); - } - }); - - final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button); - if ( okButtonOnClickListener == null ) { - ((ViewGroup) okButton.getParent()).removeView(okButton); - } else { - okButton.setOnClickListener(this.okButtonOnClickListener); - } - - final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button); - if ( customButtonData == null ) { - ((ViewGroup) customButton.getParent()).removeView(customButton); - } else { - customButton.setText(customButtonData.text); - customButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main)); - } - }); - } - - - - return main; - } - - private void fillSpinner(@NotNull final View main, - @NotNull final Context context, - final int spinnerId, - @NotNull List> unitTypes) { - final Spinner spinner = (Spinner) main.findViewById(spinnerId); - - final ArrayAdapter> adapter = new ArrayAdapter>(context, android.R.layout.simple_spinner_item); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - for (UnitType fromUnitType : unitTypes) { - adapter.add(fromUnitType); - } - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - doConversion(main, context, UnitConverterViewBuilder.this.converter); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - spinner.setAdapter(adapter); - } - - private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter converter) { - final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); - - final EditText toEditText = (EditText) main.findViewById(R.id.units_to); - - final String from = fromEditText.getText().toString(); - try { - toEditText.setText(CalculatorImpl.doConversion(converter, from, getFromUnitType(main), getToUnitType(main))); - } catch (CalculatorImpl.ConversionException e) { - toEditText.setText(context.getString(R.string.c_error)); - } - } - - @NotNull - private static Unit getToUnit(@NotNull View main) { - final EditText toUnits = (EditText) main.findViewById(R.id.units_to); - return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main)); - } - - @NotNull - private static UnitType getToUnitType(@NotNull View main) { - final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to); - return (UnitType) toSpinner.getSelectedItem(); - } - - @NotNull - private static Unit getFromUnit(@NotNull View main) { - final EditText fromUnits = (EditText) main.findViewById(R.id.units_from); - return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main)); - } - - @NotNull - private static UnitType getFromUnitType(@NotNull View main) { - final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); - return (UnitType) fromSpinner.getSelectedItem(); - } - - public static class CustomButtonData { - - @NotNull - private String text; - - @NotNull - private CustomButtonOnClickListener clickListener; - - - public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) { - this.text = text; - this.clickListener = clickListener; - } - } - - public static interface CustomButtonOnClickListener { - void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits); - } -} +package org.solovyev.android.calculator.view; + +import android.app.Activity; +import android.content.Context; +import android.text.ClipboardManager; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.view.ViewGroup; +import android.widget.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.math.units.Unit; +import org.solovyev.math.units.UnitConverter; +import org.solovyev.math.units.UnitImpl; +import org.solovyev.math.units.UnitType; +import org.solovyev.android.calculator.R; +import org.solovyev.android.view.ViewBuilder; +import org.solovyev.android.view.ViewFromLayoutBuilder; +import org.solovyev.common.text.StringUtils; + +import java.util.Collections; +import java.util.List; + +/** + * User: serso + * Date: 4/20/12 + * Time: 4:50 PM + */ +public class UnitConverterViewBuilder implements ViewBuilder { + + @NotNull + private List> fromUnitTypes = Collections.emptyList(); + + @NotNull + private List> toUnitTypes = Collections.emptyList(); + + @Nullable + private Unit fromValue; + + @NotNull + private UnitConverter converter = UnitConverter.Dummy.getInstance(); + + @Nullable + private View.OnClickListener okButtonOnClickListener; + + @Nullable + private CustomButtonData customButtonData; + + public void setFromUnitTypes(@NotNull List> fromUnitTypes) { + this.fromUnitTypes = fromUnitTypes; + } + + public void setToUnitTypes(@NotNull List> toUnitTypes) { + this.toUnitTypes = toUnitTypes; + } + + public void setFromValue(@Nullable Unit fromValue) { + this.fromValue = fromValue; + } + + public void setConverter(@NotNull UnitConverter converter) { + this.converter = converter; + } + + public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) { + this.okButtonOnClickListener = okButtonOnClickListener; + } + + public void setCustomButtonData(@Nullable CustomButtonData customButtonData) { + this.customButtonData = customButtonData; + } + + @NotNull + @Override + public View build(@NotNull final Context context) { + final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context); + + final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); + final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); + fromEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + doConversion(main, context, UnitConverterViewBuilder.this.converter); + } + }); + + fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes); + fillSpinner(main, context, R.id.unit_types_to, toUnitTypes); + + if (fromValue != null) { + fromEditText.setText(fromValue.getValue()); + + int i = fromUnitTypes.indexOf(fromValue.getUnitType()); + if ( i >= 0 ) { + fromSpinner.setSelection(i); + } + } + + final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button); + copyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final EditText toEditText = (EditText) main.findViewById(R.id.units_to); + + final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(toEditText.getText().toString()); + Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); + } + }); + + final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button); + if ( okButtonOnClickListener == null ) { + ((ViewGroup) okButton.getParent()).removeView(okButton); + } else { + okButton.setOnClickListener(this.okButtonOnClickListener); + } + + final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button); + if ( customButtonData == null ) { + ((ViewGroup) customButton.getParent()).removeView(customButton); + } else { + customButton.setText(customButtonData.text); + customButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main)); + } + }); + } + + + + return main; + } + + private void fillSpinner(@NotNull final View main, + @NotNull final Context context, + final int spinnerId, + @NotNull List> unitTypes) { + final Spinner spinner = (Spinner) main.findViewById(spinnerId); + + final ArrayAdapter> adapter = new ArrayAdapter>(context, android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + for (UnitType fromUnitType : unitTypes) { + adapter.add(fromUnitType); + } + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + doConversion(main, context, UnitConverterViewBuilder.this.converter); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + spinner.setAdapter(adapter); + } + + private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter converter) { + final EditText fromEditText = (EditText) main.findViewById(R.id.units_from); + + final EditText toEditText = (EditText) main.findViewById(R.id.units_to); + + final String from = fromEditText.getText().toString(); + try { + toEditText.setText(doConversion(converter, from, getFromUnitType(main), getToUnitType(main))); + } catch (ConversionException e) { + toEditText.setText(context.getString(R.string.c_error)); + } + } + + public static final class ConversionException extends Exception { + private ConversionException() { + } + + private ConversionException(Throwable throwable) { + super(throwable); + } + } + + @NotNull + public static String doConversion(@NotNull UnitConverter converter, + @Nullable String from, + @NotNull UnitType fromUnitType, + @NotNull UnitType toUnitType) throws ConversionException{ + final String result; + + if (StringUtils.isEmpty(from)) { + result = ""; + } else { + + String to = null; + try { + if (converter.isSupported(fromUnitType, toUnitType)) { + to = converter.convert(UnitImpl.newInstance(from, fromUnitType), toUnitType).getValue(); + } + } catch (RuntimeException e) { + throw new ConversionException(e); + } + + result = to; + } + + return result; + } + + @NotNull + private static Unit getToUnit(@NotNull View main) { + final EditText toUnits = (EditText) main.findViewById(R.id.units_to); + return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main)); + } + + @NotNull + private static UnitType getToUnitType(@NotNull View main) { + final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to); + return (UnitType) toSpinner.getSelectedItem(); + } + + @NotNull + private static Unit getFromUnit(@NotNull View main) { + final EditText fromUnits = (EditText) main.findViewById(R.id.units_from); + return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main)); + } + + @NotNull + private static UnitType getFromUnitType(@NotNull View main) { + final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from); + return (UnitType) fromSpinner.getSelectedItem(); + } + + public static class CustomButtonData { + + @NotNull + private String text; + + @NotNull + private CustomButtonOnClickListener clickListener; + + + public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) { + this.text = text; + this.clickListener = clickListener; + } + } + + public static interface CustomButtonOnClickListener { + void onClick(@NotNull Unit fromUnits, @NotNull Unit toUnits); + } +} From db9b676cfa03c7b4f917c46db1f33caf0badb34b Mon Sep 17 00:00:00 2001 From: serso Date: Fri, 21 Sep 2012 10:38:07 +0400 Subject: [PATCH 2/3] Revert recent changes, see dev branch --- calculatorpp-core/pom.xml | 46 - .../android/calculator/Calculator.java | 25 - .../android/calculator/CalculatorDisplay.java | 28 - .../calculator/CalculatorDisplayImpl.java | 147 --- .../calculator/CalculatorDisplayView.java | 16 - .../CalculatorDisplayViewState.java | 33 - .../CalculatorDisplayViewStateImpl.java | 104 -- .../CalculatorEvaluationEventData.java | 18 - .../CalculatorEvaluationEventDataImpl.java | 58 -- .../calculator/CalculatorEventContainer.java | 57 -- .../calculator/CalculatorEventData.java | 10 - .../calculator/CalculatorEventDataId.java | 20 - .../calculator/CalculatorEventDataIdImpl.java | 66 -- .../calculator/CalculatorEventDataImpl.java | 57 -- .../calculator/CalculatorEventListener.java | 17 - .../calculator/CalculatorEventType.java | 43 - .../android/calculator/CalculatorFailure.java | 21 - .../calculator/CalculatorFailureImpl.java | 34 - .../android/calculator/CalculatorImpl.java | 209 ----- .../android/calculator/CalculatorInput.java | 18 - .../calculator/CalculatorInputImpl.java | 35 - .../android/calculator/CalculatorLocator.java | 22 - .../calculator/CalculatorLocatorImpl.java | 54 -- .../android/calculator/CalculatorMessage.java | 31 - .../calculator/CalculatorMessages.java | 69 -- .../android/calculator/CalculatorOutput.java | 22 - .../calculator/CalculatorOutputImpl.java | 46 - .../android/calculator/JCalculatorEngine.java | 34 - .../ListCalculatorEventContainer.java | 50 - .../calculator/history/CalculatorHistory.java | 20 - .../history/CalculatorHistoryImpl.java | 131 --- .../common/utils/ListListenersContainer.java | 77 -- .../android/calculator/messages.properties | 8 - calculatorpp-service/pom.xml | 1 + calculatorpp/pom.xml | 39 +- calculatorpp/res/layout/calc_display.xml | 30 +- .../main/java/org/solovyev/android}/Unit.java | 2 +- .../org/solovyev/android}/UnitConverter.java | 2 +- .../java/org/solovyev/android}/UnitImpl.java | 2 +- .../java/org/solovyev/android}/UnitType.java | 2 +- .../calculator/AndroidNumeralBase.java | 8 +- .../calculator/CalculatorActivity.java | 4 +- .../calculator/CalculatorApplication.java | 2 - ...isplayView.java => CalculatorDisplay.java} | 272 +++--- .../android/calculator/CalculatorEditor.java | 3 +- .../calculator/CalculatorEngineControl.java | 0 .../android/calculator/CalculatorModel.java | 59 +- .../calculator/ICalculatorDisplay.java | 40 + .../history/AbstractHistoryActivity.java | 2 +- .../history/AbstractHistoryState.java | 1 + .../history/AndroidCalculatorHistory.java | 18 - .../history/AndroidCalculatorHistoryImpl.java | 145 --- .../CalculatorDisplayHistoryState.java | 282 +++--- .../calculator/history/CalculatorHistory.java | 149 +++ .../history/CalculatorHistoryState.java | 221 +++-- .../android/calculator/history}/Editor.java | 2 +- .../history/EditorHistoryState.java | 186 ++-- .../android/calculator/history/History.java | 0 .../history/HistoryActivityTab.java | 4 +- .../history/HistoryItemMenuItem.java | 8 +- .../calculator/history/HistoryUtils.java | 0 .../history/SavedHistoryActivityTab.java | 4 +- .../history/TextViewEditorAdapter.java | 1 - .../jscl/FromJsclNumericTextProcessor.java | 4 +- .../calculator/jscl/JsclOperation.java | 20 +- .../android/calculator/math/MathType.java | 19 +- .../model}/AbstractNumberBuilder.java | 2 +- .../calculator/model/CalculatorEngine.java | 829 ++++++++-------- .../model}/CalculatorEvalException.java | 3 +- .../model}/CalculatorParseException.java | 15 +- .../calculator/model}/DummyTextProcessor.java | 3 +- .../model}/FromJsclSimplifyTextProcessor.java | 6 +- .../calculator/model}/LiteNumberBuilder.java | 2 +- .../calculator/model}/NumberBuilder.java | 5 +- .../calculator/model}/PreparedExpression.java | 2 +- .../calculator/model}/TextProcessor.java | 3 +- .../model}/ToJsclTextProcessor.java | 13 +- .../plot/CalculatorPlotActivity.java | 6 +- .../view/NumeralBaseConverterDialog.java | 8 +- .../calculator/view/TextHighlighter.java | 5 - .../view/UnitConverterViewBuilder.java | 8 +- .../android/AndroidNumeralBaseTest.java | 2 - .../calculator/TextHighlighterTest.java | 2 +- .../calculator/history/HistoryUtilsTest.java | 641 +++++++------ .../model/CalculatorEngineTest.java | 888 +++++++++--------- .../FromJsclSimplifyTextProcessorTest.java | 1 - .../calculator/model/NumeralBaseTest.java | 294 +++--- .../model/ToJsclTextProcessorTest.java | 4 - pom.xml | 37 +- 89 files changed, 2161 insertions(+), 3776 deletions(-) delete mode 100644 calculatorpp-core/pom.xml delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayView.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewState.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewStateImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventContainer.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventListener.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailure.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInput.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInputImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessage.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessages.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutput.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutputImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/JCalculatorEngine.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java delete mode 100644 calculatorpp-core/src/main/java/org/solovyev/common/utils/ListListenersContainer.java delete mode 100644 calculatorpp-core/src/main/resources/org/solovyev/android/calculator/messages.properties rename {calculatorpp-core/src/main/java/org/solovyev/math/units => calculatorpp/src/main/java/org/solovyev/android}/Unit.java (80%) rename {calculatorpp-core/src/main/java/org/solovyev/math/units => calculatorpp/src/main/java/org/solovyev/android}/UnitConverter.java (92%) rename {calculatorpp-core/src/main/java/org/solovyev/math/units => calculatorpp/src/main/java/org/solovyev/android}/UnitImpl.java (90%) rename {calculatorpp-core/src/main/java/org/solovyev/math/units => calculatorpp/src/main/java/org/solovyev/android}/UnitType.java (81%) rename calculatorpp/src/main/java/org/solovyev/android/calculator/{AndroidCalculatorDisplayView.java => CalculatorDisplay.java} (52%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/CalculatorEngineControl.java (100%) create mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/ICalculatorDisplay.java rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java (91%) delete mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java delete mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistoryImpl.java rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java (68%) create mode 100644 calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java (91%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/history}/Editor.java (85%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java (82%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/History.java (100%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/history/HistoryUtils.java (100%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java (80%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java (55%) rename {calculatorpp-core => calculatorpp}/src/main/java/org/solovyev/android/calculator/math/MathType.java (91%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/AbstractNumberBuilder.java (95%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/CalculatorEvalException.java (89%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/CalculatorParseException.java (71%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator/text => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/DummyTextProcessor.java (78%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator/text => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/FromJsclSimplifyTextProcessor.java (86%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/LiteNumberBuilder.java (92%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/NumberBuilder.java (94%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/PreparedExpression.java (91%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator/text => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/TextProcessor.java (65%) rename {calculatorpp-core/src/main/java/org/solovyev/android/calculator => calculatorpp/src/main/java/org/solovyev/android/calculator/model}/ToJsclTextProcessor.java (82%) diff --git a/calculatorpp-core/pom.xml b/calculatorpp-core/pom.xml deleted file mode 100644 index 17ae2ad2..00000000 --- a/calculatorpp-core/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - org.solovyev.android - calculatorpp-parent - 1.3.1 - - - org.solovyev.android - calculatorpp-core - 1.3.1 - Calculator++ Application Core - - jar - - - - - junit - junit - test - - - - com.intellij - annotations - - - - org.solovyev - jscl - - - - org.simpleframework - simple-xml - - - - - - \ No newline at end of file diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java deleted file mode 100644 index 28b2ae45..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Calculator.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.msg.MessageRegistry; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:38 - */ -public interface Calculator extends CalculatorEventContainer { - - @NotNull - CalculatorEventDataId createFirstEventDataId(); - - void evaluate(@NotNull JsclOperation operation, - @NotNull String expression); - - @NotNull - CalculatorEventDataId evaluate(@NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java deleted file mode 100644 index a68d9747..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - * or visit http://se.solovyev.org - */ - -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: serso - * Date: 12/17/11 - * Time: 9:45 PM - */ -public interface CalculatorDisplay extends CalculatorEventListener { - - void setView(@Nullable CalculatorDisplayView view); - - @NotNull - CalculatorDisplayViewState getViewState(); - - void setViewState(@NotNull CalculatorDisplayViewState viewState); - - @NotNull - CalculatorEventData getLastEventData(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java deleted file mode 100644 index 5e794275..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayImpl.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import static org.solovyev.android.calculator.CalculatorEventType.*; - -/** - * User: serso - * Date: 9/20/12 - * Time: 8:24 PM - */ -public class CalculatorDisplayImpl implements CalculatorDisplay { - - @NotNull - private CalculatorEventData lastCalculatorEventData = CalculatorEventDataImpl.newInstance(CalculatorLocatorImpl.getInstance().getCalculator().createFirstEventDataId()); - - @Nullable - private CalculatorDisplayView view; - - @NotNull - private final Object viewLock = new Object(); - - @NotNull - private CalculatorDisplayViewState lastViewState = CalculatorDisplayViewStateImpl.newDefaultInstance(); - - @Override - public void setView(@Nullable CalculatorDisplayView view) { - synchronized (viewLock) { - this.view = view; - - if (view != null) { - this.view.setState(lastViewState); - } - } - } - - @NotNull - @Override - public CalculatorDisplayViewState getViewState() { - return this.lastViewState; - } - - @Override - public void setViewState(@NotNull CalculatorDisplayViewState viewState) { - synchronized (viewLock) { - this.lastViewState = viewState; - if (this.view != null) { - this.view.setState(viewState); - } - } - } - -/* @Override - @Nullable - public CharSequence getText() { - synchronized (viewLock) { - return view != null ? view.getText() : null; - } - } - - @Override - public void setText(@Nullable CharSequence text) { - synchronized (viewLock) { - if (view != null) { - view.setText(text); - } - } - } - - @Override - public int getSelection() { - synchronized (viewLock) { - return view != null ? view.getSelection() : 0; - } - } - - @Override - public void setSelection(int selection) { - synchronized (viewLock) { - if (view != null) { - view.setSelection(selection); - } - } - }*/ - - @Override - @NotNull - public CalculatorEventData getLastEventData() { - return lastCalculatorEventData; - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEventType calculatorEventType, - @Nullable Object data) { - if (calculatorEventType.isOfType(calculation_result, calculation_failed, calculation_cancelled)) { - - if (calculatorEventData.isAfter(lastCalculatorEventData)) { - lastCalculatorEventData = calculatorEventData; - } - - switch (calculatorEventType) { - 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; - } - - } - } - - private void processCalculationFailed(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorFailure data) { - - final CalculatorEvalException calculatorEvalException = data.getCalculationEvalException(); - - 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.setViewState(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage)); - } - - private void processCalculationCancelled(@NotNull CalculatorEvaluationEventData calculatorEventData) { - final String errorMessage = CalculatorMessages.getBundle().getString(CalculatorMessages.syntax_error); - - this.setViewState(CalculatorDisplayViewStateImpl.newErrorState(calculatorEventData.getOperation(), errorMessage)); - } - - private void processCalculationResult(@NotNull CalculatorEvaluationEventData calculatorEventData, @NotNull CalculatorOutput data) { - final String stringResult = data.getStringResult(); - this.setViewState(CalculatorDisplayViewStateImpl.newValidState(calculatorEventData.getOperation(), data.getResult(), stringResult, 0)); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayView.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayView.java deleted file mode 100644 index 5ddc45df..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayView.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: serso - * Date: 9/20/12 - * Time: 8:25 PM - */ -public interface CalculatorDisplayView { - - void setState(@NotNull CalculatorDisplayViewState state); - - @NotNull - CalculatorDisplayViewState getState(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewState.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewState.java deleted file mode 100644 index 2fdc83b3..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewState.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 9:50 PM - */ -public interface CalculatorDisplayViewState { - - @NotNull - String getText(); - - int getSelection(); - - @Nullable - Generic getResult(); - - boolean isValid(); - - @Nullable - String getErrorMessage(); - - @NotNull - JsclOperation getOperation(); - - @Nullable - String getStringResult(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewStateImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewStateImpl.java deleted file mode 100644 index ac13a9bc..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorDisplayViewStateImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.text.StringUtils; - -/** - * User: serso - * Date: 9/20/12 - * Time: 9:50 PM - */ -public class CalculatorDisplayViewStateImpl implements CalculatorDisplayViewState { - - @NotNull - private JsclOperation operation = JsclOperation.numeric; - - @Nullable - private Generic result; - - @Nullable - private String stringResult = ""; - - private boolean valid = true; - - @Nullable - private String errorMessage; - - private int selection = 0; - - private CalculatorDisplayViewStateImpl() { - } - - @NotNull - public static CalculatorDisplayViewState newDefaultInstance() { - return new CalculatorDisplayViewStateImpl(); - } - - @NotNull - public static CalculatorDisplayViewState newErrorState(@NotNull JsclOperation operation, - @NotNull String errorMessage) { - final CalculatorDisplayViewStateImpl calculatorDisplayState = new CalculatorDisplayViewStateImpl(); - calculatorDisplayState.valid = false; - calculatorDisplayState.errorMessage = errorMessage; - calculatorDisplayState.operation = operation; - return calculatorDisplayState; - } - - @NotNull - public static CalculatorDisplayViewState newValidState(@NotNull JsclOperation operation, - @Nullable Generic result, - @NotNull 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; - } - - @NotNull - @Override - public String getText() { - return StringUtils.getNotEmpty(isValid() ? stringResult : errorMessage, ""); - } - - @Override - public int getSelection() { - return selection; - } - - @Nullable - @Override - public Generic getResult() { - return this.result; - } - - @Override - public boolean isValid() { - return this.valid; - } - - @Nullable - @Override - public String getErrorMessage() { - return this.errorMessage; - } - - @Override - @Nullable - public String getStringResult() { - return stringResult; - } - - @NotNull - @Override - public JsclOperation getOperation() { - return this.operation; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java deleted file mode 100644 index 45c74178..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventData.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 10:00 PM - */ -public interface CalculatorEvaluationEventData extends CalculatorEventData{ - - @NotNull - JsclOperation getOperation(); - - @NotNull - String getExpression(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java deleted file mode 100644 index f40cd6cf..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvaluationEventDataImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 10:01 PM - */ -public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEventData { - - @NotNull - private final CalculatorEventData calculatorEventData; - - @NotNull - private final JsclOperation operation; - - @NotNull - private final String expression; - - public CalculatorEvaluationEventDataImpl(@NotNull CalculatorEventData calculatorEventData, - @NotNull JsclOperation operation, - @NotNull String expression) { - this.calculatorEventData = calculatorEventData; - this.operation = operation; - this.expression = expression; - } - - @NotNull - @Override - public JsclOperation getOperation() { - return this.operation; - } - - @NotNull - @Override - public String getExpression() { - return this.expression; - } - - @Override - public long getEventId() { - return calculatorEventData.getEventId(); - } - - @Override - @Nullable - public Long getCalculationId() { - return calculatorEventData.getCalculationId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return calculatorEventData.isAfter(calculatorEventDataId); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventContainer.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventContainer.java deleted file mode 100644 index 20d918d6..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventContainer.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:39 - */ -public interface CalculatorEventContainer { - - void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener); - - void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener); - - void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data); - - void fireCalculatorEvents(@NotNull List calculatorEvents); - - public static class CalculatorEvent { - - @NotNull - private CalculatorEventData calculatorEventData; - - @NotNull - private CalculatorEventType calculatorEventType; - - @Nullable - private Object data; - - public CalculatorEvent(@NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEventType calculatorEventType, - @Nullable Object data) { - this.calculatorEventData = calculatorEventData; - this.calculatorEventType = calculatorEventType; - this.data = data; - } - - @NotNull - public CalculatorEventData getCalculatorEventData() { - return calculatorEventData; - } - - @NotNull - public CalculatorEventType getCalculatorEventType() { - return calculatorEventType; - } - - @Nullable - public Object getData() { - return data; - } - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java deleted file mode 100644 index 567808a7..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventData.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.solovyev.android.calculator; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:51 - */ -public interface CalculatorEventData extends CalculatorEventDataId { - -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java deleted file mode 100644 index f77558cd..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataId.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 18:18 - */ -public interface CalculatorEventDataId { - - // the higher id => the later event - long getEventId(); - - @Nullable - Long getCalculationId(); - - boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java deleted file mode 100644 index 0eb8d4a0..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataIdImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 18:18 - */ -class CalculatorEventDataIdImpl implements CalculatorEventDataId { - - private final long eventId; - - @Nullable - private final Long calculationId; - - private CalculatorEventDataIdImpl(long id, - @Nullable Long calculationId) { - this.eventId = id; - this.calculationId = calculationId; - } - - @NotNull - static CalculatorEventDataId newInstance(long id, - @Nullable Long calculationId) { - return new CalculatorEventDataIdImpl(id, calculationId); - } - - @Override - public long getEventId() { - return this.eventId; - } - - @Nullable - @Override - public Long getCalculationId() { - return this.calculationId; - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return this.eventId > calculatorEventDataId.getEventId(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CalculatorEventDataIdImpl)) return false; - - CalculatorEventDataIdImpl that = (CalculatorEventDataIdImpl) o; - - if (eventId != that.eventId) return false; - if (calculationId != null ? !calculationId.equals(that.calculationId) : that.calculationId != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = (int) (eventId ^ (eventId >>> 32)); - result = 31 * result + (calculationId != null ? calculationId.hashCode() : 0); - return result; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java deleted file mode 100644 index 4f7151ce..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventDataImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:54 - */ -class CalculatorEventDataImpl implements CalculatorEventData { - - @NotNull - private CalculatorEventDataId calculatorEventDataId; - - private CalculatorEventDataImpl(@NotNull CalculatorEventDataId calculatorEventDataId) { - this.calculatorEventDataId = calculatorEventDataId; - } - - @NotNull - public static CalculatorEventData newInstance(@NotNull CalculatorEventDataId calculatorEventDataId) { - return new CalculatorEventDataImpl(calculatorEventDataId); - } - - @Override - public long getEventId() { - return calculatorEventDataId.getEventId(); - } - - @Override - @Nullable - public Long getCalculationId() { - return calculatorEventDataId.getCalculationId(); - } - - @Override - public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { - return this.calculatorEventDataId.isAfter(calculatorEventDataId); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CalculatorEventDataImpl)) return false; - - CalculatorEventDataImpl that = (CalculatorEventDataImpl) o; - - if (!calculatorEventDataId.equals(that.calculatorEventDataId)) return false; - - return true; - } - - @Override - public int hashCode() { - return calculatorEventDataId.hashCode(); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventListener.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventListener.java deleted file mode 100644 index ea4a34f6..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.EventListener; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:39 - */ -public interface CalculatorEventListener extends EventListener { - - void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data); - -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java deleted file mode 100644 index 95568893..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:40 - */ -public enum CalculatorEventType { - - /* - ********************************************************************** - * - * org.solovyev.android.calculator.CalculatorEvaluationEventData - * - ********************************************************************** - */ - - // @NotNull org.solovyev.android.calculator.CalculatorInput - calculation_started, - - // @NotNull org.solovyev.android.calculator.CalculatorOutput - calculation_result, - - calculation_cancelled, - - calculation_finished, - - // @NotNull org.solovyev.android.calculator.CalculatorFailure - calculation_failed; - - public boolean isOfType(@NotNull CalculatorEventType... types) { - for (CalculatorEventType type : types) { - if ( this == type ) { - return true; - } - } - - return false; - } - -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailure.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailure.java deleted file mode 100644 index 5d07bb40..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailure.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: serso - * Date: 9/20/12 - * Time: 7:33 PM - */ -public interface CalculatorFailure { - - @NotNull - Exception getException(); - - @Nullable - CalculatorParseException getCalculationParseException(); - - @Nullable - CalculatorEvalException getCalculationEvalException(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java deleted file mode 100644 index 866146b3..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: serso - * Date: 9/20/12 - * Time: 7:34 PM - */ -public class CalculatorFailureImpl implements CalculatorFailure { - - @NotNull - private Exception exception; - - public CalculatorFailureImpl(@NotNull Exception exception) { - this.exception = exception; - } - - @NotNull - @Override - public Exception getException() { - return this.exception; - } - - @Override - public CalculatorParseException getCalculationParseException() { - return exception instanceof CalculatorParseException ? (CalculatorParseException)exception : null; - } - - @Override - public CalculatorEvalException getCalculationEvalException() { - return exception instanceof CalculatorEvalException ? (CalculatorEvalException)exception : null; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java deleted file mode 100644 index 1e299d59..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.AbstractJsclArithmeticException; -import jscl.NumeralBaseException; -import jscl.math.Generic; -import jscl.text.ParseInterruptedException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.common.msg.MessageRegistry; -import org.solovyev.common.msg.MessageType; - -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicLong; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:42 - */ -public class CalculatorImpl implements Calculator { - - private static final long FIRST_ID = 0; - - @NotNull - private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); - - @NotNull - private final AtomicLong counter = new AtomicLong(FIRST_ID); - - @NotNull - private final Object lock = new Object(); - - @NotNull - private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); - - @NotNull - private final Executor threadPoolExecutor = Executors.newFixedThreadPool(10); - - public CalculatorImpl() { - } - - @NotNull - private CalculatorEventDataId nextCalculatorEventDataId() { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataIdImpl.newInstance(eventId, eventId); - } - - @NotNull - private CalculatorEventDataId nextEventDataId(@NotNull Long calculationId) { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataIdImpl.newInstance(eventId, calculationId); - } - - /* - ********************************************************************** - * - * CALCULATION - * - ********************************************************************** - */ - - @NotNull - @Override - public CalculatorEventDataId createFirstEventDataId() { - return CalculatorEventDataIdImpl.newInstance(FIRST_ID, FIRST_ID); - } - - @Override - public void evaluate(@NotNull JsclOperation operation, - @NotNull String expression) { - evaluate(operation, expression, null); - } - - @Override - @NotNull - public CalculatorEventDataId evaluate(@NotNull final JsclOperation operation, - @NotNull final String expression, - @Nullable final MessageRegistry mr) { - - final CalculatorEventDataId eventDataId = nextCalculatorEventDataId(); - - threadPoolExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getCalculationId(), operation, expression, mr); - } - }); - - return eventDataId; - } - - private void evaluate(@NotNull Long calculationId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr) { - synchronized (lock) { - - PreparedExpression preparedExpression = null; - - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); - - try { - preparedExpression = preprocessor.process(expression); - - final String jsclExpression = preparedExpression.toString(); - - try { - - final Generic result = operation.evaluateGeneric(jsclExpression); - - // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) - result.toString(); - - final CalculatorOutputImpl data = new CalculatorOutputImpl(operation.getFromProcessor().process(result), operation, result); - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_result, data); - - } catch (AbstractJsclArithmeticException e) { - handleException(calculationId, operation, expression, mr, new CalculatorEvalException(e, e, jsclExpression)); - } - - } catch (ArithmeticException e) { - handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_001, MessageType.error, e.getMessage()))); - } catch (StackOverflowError e) { - handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(expression, new CalculatorMessage(CalculatorMessages.msg_002, MessageType.error))); - } catch (jscl.text.ParseException e) { - handleException(calculationId, operation, expression, mr, preparedExpression, new CalculatorParseException(e)); - } catch (ParseInterruptedException e) { - - // do nothing - we ourselves interrupt the calculations - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_cancelled, null); - - } catch (CalculatorParseException e) { - handleException(calculationId, operation, expression, mr, preparedExpression, e); - } finally { - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_finished, null); - } - } - } - - @NotNull - private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation, - @NotNull String expression, - @NotNull Long calculationId) { - return new CalculatorEvaluationEventDataImpl(CalculatorEventDataImpl.newInstance(nextEventDataId(calculationId)), operation, expression); - } - - private void handleException(@NotNull Long calculationId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @Nullable PreparedExpression preparedExpression, - @NotNull CalculatorParseException parseException) { - - if (operation == JsclOperation.numeric - && preparedExpression != null - && preparedExpression.isExistsUndefinedVar()) { - - evaluate(calculationId, JsclOperation.simplify, expression, mr); - - } - - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(parseException)); - } - - private void handleException(@NotNull Long calculationId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @NotNull CalculatorEvalException evalException) { - - if (operation == JsclOperation.numeric && evalException.getCause() instanceof NumeralBaseException) { - evaluate(calculationId, JsclOperation.simplify, expression, mr); - } - - fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException)); - } - - /* - ********************************************************************** - * - * EVENTS - * - ********************************************************************** - */ - - @Override - public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculatorEventContainer.addCalculatorEventListener(calculatorEventListener); - } - - @Override - public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - calculatorEventContainer.removeCalculatorEventListener(calculatorEventListener); - } - - @Override - public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); - } - - @Override - public void fireCalculatorEvents(@NotNull List calculatorEvents) { - calculatorEventContainer.fireCalculatorEvents(calculatorEvents); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInput.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInput.java deleted file mode 100644 index 1f0c98ab..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInput.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 7:25 PM - */ -public interface CalculatorInput { - - @NotNull - String getExpression(); - - @NotNull - JsclOperation getOperation(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInputImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInputImpl.java deleted file mode 100644 index 2ad4608c..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorInputImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 7:26 PM - */ -public class CalculatorInputImpl implements CalculatorInput { - - @NotNull - private String expression; - - @NotNull - private JsclOperation operation; - - public CalculatorInputImpl(@NotNull String expression, @NotNull JsclOperation operation) { - this.expression = expression; - this.operation = operation; - } - - @Override - @NotNull - public String getExpression() { - return expression; - } - - @Override - @NotNull - public JsclOperation getOperation() { - return operation; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java deleted file mode 100644 index 3b04e8be..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 12:45 - */ -public interface CalculatorLocator { - - @NotNull - JCalculatorEngine getCalculatorEngine(); - - @NotNull - Calculator getCalculator(); - - @NotNull - CalculatorDisplay getCalculatorDisplay(); - - void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java deleted file mode 100644 index 989e1445..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 12:45 - */ -public class CalculatorLocatorImpl implements CalculatorLocator { - - @NotNull - private JCalculatorEngine calculatorEngine; - - @NotNull - private CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl(); - - @NotNull - private Calculator calculator = new CalculatorImpl(); - - @NotNull - private static final CalculatorLocator instance = new CalculatorLocatorImpl(); - - private CalculatorLocatorImpl() { - } - - @NotNull - public static CalculatorLocator getInstance() { - return instance; - } - - @NotNull - @Override - public JCalculatorEngine getCalculatorEngine() { - return calculatorEngine; - } - - @NotNull - @Override - public Calculator getCalculator() { - return this.calculator; - } - - @Override - public void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine) { - this.calculatorEngine = calculatorEngine; - } - - @Override - @NotNull - public CalculatorDisplay getCalculatorDisplay() { - return calculatorDisplay; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessage.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessage.java deleted file mode 100644 index ab7e1763..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessage.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.common.msg.AbstractMessage; -import org.solovyev.common.msg.MessageType; - -import java.util.List; -import java.util.Locale; -import java.util.ResourceBundle; - -/** - * User: serso - * Date: 9/20/12 - * Time: 8:06 PM - */ -public class CalculatorMessage extends AbstractMessage { - - protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @org.jetbrains.annotations.Nullable Object... parameters) { - super(messageCode, messageType, parameters); - } - - protected CalculatorMessage(@NotNull String messageCode, @NotNull MessageType messageType, @NotNull List parameters) { - super(messageCode, messageType, parameters); - } - - @Override - protected String getMessagePattern(@NotNull Locale locale) { - final ResourceBundle rb = CalculatorMessages.getBundle(locale); - return rb.getString(getMessageCode()); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessages.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessages.java deleted file mode 100644 index aa21657b..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorMessages.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; - -/** - * User: serso - * Date: 9/20/12 - * Time: 8:10 PM - */ -public final class CalculatorMessages { - - @NotNull - private static final Map bundlesByLocale = new HashMap(); - - private CalculatorMessages() { - throw new AssertionError(); - } - - @NotNull - public static ResourceBundle getBundle() { - return getBundle(Locale.getDefault()); - } - - @NotNull - public static ResourceBundle getBundle(@NotNull Locale locale) { - synchronized (bundlesByLocale) { - ResourceBundle result = bundlesByLocale.get(locale); - if (result == null) { - result = ResourceBundle.getBundle("org/solovyev/android/calculator/messages", locale); - bundlesByLocale.put(locale, result); - } - - return result; - } - } - - /* Arithmetic error occurred: {0} */ - @NotNull - public static final String msg_001 = "msg_1"; - - /* Too complex expression*/ - @NotNull - public static final String msg_002 = "msg_2"; - - /* Too long execution time - check the expression*/ - @NotNull - public static final String msg_003 = "msg_3"; - - /* Evaluation was cancelled*/ - @NotNull - public static final String msg_004 = "msg_4"; - - /* No parameters are specified for function: {0}*/ - @NotNull - public static final String msg_005 = "msg_5"; - - /* Infinite loop is detected in expression*/ - @NotNull - public static final String msg_006 = "msg_6"; - - /* Error */ - @NotNull - public static final String syntax_error = "syntax_error"; -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutput.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutput.java deleted file mode 100644 index bac56104..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutput.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** - * User: serso - * Date: 9/20/12 - * Time: 7:29 PM - */ -public interface CalculatorOutput { - - @NotNull - String getStringResult(); - - @NotNull - JsclOperation getOperation(); - - @NotNull - Generic getResult(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutputImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutputImpl.java deleted file mode 100644 index 0ca7e1fe..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorOutputImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.jscl.JsclOperation; - -/** -* User: serso -* Date: 9/20/12 -* Time: 7:28 PM -*/ -public class CalculatorOutputImpl implements CalculatorOutput { - - @NotNull - private Generic result; - - @NotNull - private String stringResult; - - @NotNull - private JsclOperation operation; - - public CalculatorOutputImpl(@NotNull String stringResult, @NotNull JsclOperation operation, @NotNull Generic result) { - this.stringResult = stringResult; - this.operation = operation; - this.result = result; - } - - @Override - @NotNull - public String getStringResult() { - return stringResult; - } - - @Override - @NotNull - public JsclOperation getOperation() { - return operation; - } - - @Override - @NotNull - public Generic getResult() { - return result; - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/JCalculatorEngine.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/JCalculatorEngine.java deleted file mode 100644 index c069e378..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/JCalculatorEngine.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.solovyev.android.calculator; - -import jscl.MathEngine; -import jscl.math.function.Function; -import jscl.math.function.IConstant; -import jscl.math.operator.Operator; -import org.jetbrains.annotations.NotNull; -import org.solovyev.common.math.MathRegistry; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 12:43 - */ -public interface JCalculatorEngine { - - @NotNull - String getMultiplicationSign(); - - @NotNull - MathRegistry getVarsRegistry(); - - @NotNull - MathRegistry getFunctionsRegistry(); - - @NotNull - MathRegistry getOperatorsRegistry(); - - @NotNull - MathRegistry getPostfixFunctionsRegistry(); - - @NotNull - MathEngine getEngine(); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java deleted file mode 100644 index 09f18ce8..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.solovyev.android.calculator; - -import android.util.Log; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.common.utils.ListListenersContainer; - -import java.util.Arrays; -import java.util.List; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:42 - */ -public class ListCalculatorEventContainer implements CalculatorEventContainer { - - @NotNull - private static final String TAG = "CalculatorEventData"; - - @NotNull - private final ListListenersContainer listeners = new ListListenersContainer(); - - @Override - public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - listeners.addListener(calculatorEventListener); - } - - @Override - public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) { - listeners.removeListener(calculatorEventListener); - } - - @Override - public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - fireCalculatorEvents(Arrays.asList(new CalculatorEvent(calculatorEventData, calculatorEventType, data))); - } - - @Override - public void fireCalculatorEvents(@NotNull List calculatorEvents) { - final List listeners = this.listeners.getListeners(); - - for (CalculatorEvent e : calculatorEvents) { - Log.d(TAG, "Event: " + e.getCalculatorEventType() + " with data: " + e.getData()); - for (CalculatorEventListener listener : listeners) { - listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData()); - } - } - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java deleted file mode 100644 index c7f8f828..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.common.history.HistoryHelper; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:11 - */ -public interface CalculatorHistory extends HistoryHelper { - - void fromXml(@NotNull String xml); - - String toXml(); - - void clearSavedHistory(); - - void removeSavedHistory(@NotNull CalculatorHistoryState historyState); -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java deleted file mode 100644 index fc881c5c..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.common.history.HistoryAction; -import org.solovyev.common.history.HistoryHelper; -import org.solovyev.common.history.SimpleHistoryHelper; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:12 - */ -public class CalculatorHistoryImpl implements CalculatorHistory { - - private final AtomicInteger counter = new AtomicInteger(0); - - @NotNull - private final HistoryHelper history = new SimpleHistoryHelper(); - - @NotNull - private final List savedHistory = new ArrayList(); - - @Override - public boolean isEmpty() { - return this.history.isEmpty(); - } - - @Override - public CalculatorHistoryState getLastHistoryState() { - return this.history.getLastHistoryState(); - } - - @Override - public boolean isUndoAvailable() { - return history.isUndoAvailable(); - } - - @Override - public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { - return history.undo(currentState); - } - - @Override - public boolean isRedoAvailable() { - return history.isRedoAvailable(); - } - - @Override - public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { - return history.redo(currentState); - } - - @Override - public boolean isActionAvailable(@NotNull HistoryAction historyAction) { - return history.isActionAvailable(historyAction); - } - - @Override - public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { - return history.doAction(historyAction, currentState); - } - - @Override - public void addState(@Nullable CalculatorHistoryState currentState) { - history.addState(currentState); - } - - @NotNull - @Override - public List getStates() { - return history.getStates(); - } - - @Override - public void clear() { - this.history.clear(); - } - - @NotNull - public List getSavedHistory() { - return Collections.unmodifiableList(savedHistory); - } - - @NotNull - public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { - if (historyState.isSaved()) { - return historyState; - } else { - final CalculatorHistoryState savedState = historyState.clone(); - - savedState.setId(counter.incrementAndGet()); - savedState.setSaved(true); - - savedHistory.add(savedState); - - return savedState; - } - } - - @Override - public void fromXml(@NotNull String xml) { - clearSavedHistory(); - - 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 void clearSavedHistory() { - this.savedHistory.clear(); - } - - @Override - public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { - this.savedHistory.remove(historyState); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/common/utils/ListListenersContainer.java b/calculatorpp-core/src/main/java/org/solovyev/common/utils/ListListenersContainer.java deleted file mode 100644 index fa286f42..00000000 --- a/calculatorpp-core/src/main/java/org/solovyev/common/utils/ListListenersContainer.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.solovyev.common.utils; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:43 - */ -// todo serso: move to common -public class ListListenersContainer { - - @NotNull - private final List> listeners = new ArrayList>(); - - public void addListener(@NotNull final T listener) { - synchronized (listeners) { - boolean contains = Iterables.any(listeners, new WeakReferencePredicate(listener)); - - if (!contains) { - listeners.add(new WeakReference(listener)); - } - } - } - - public void removeListener(@NotNull T listener) { - synchronized (listeners) { - Iterables.removeIf(listeners, new WeakReferencePredicate(listener)); - } - } - - @NotNull - public List getListeners() { - final List localListeners; - - synchronized (listeners) { - localListeners = new ArrayList(listeners.size()); - - // copy listeners and remove garbage collected references - for ( Iterator> it = listeners.iterator(); it.hasNext(); ) { - final WeakReference r = it.next(); - final T t = r.get(); - if ( t == null ) { - it.remove(); - } else { - localListeners.add(t); - } - } - } - - return localListeners; - } - - private static class WeakReferencePredicate implements Predicate> { - - @NotNull - private final T t; - - public WeakReferencePredicate(T t) { - this.t = t; - } - - @Override - public boolean apply(@Nullable WeakReference r) { - final T t = r != null ? r.get() : null; - return this.t.equals(t); - } - } -} diff --git a/calculatorpp-core/src/main/resources/org/solovyev/android/calculator/messages.properties b/calculatorpp-core/src/main/resources/org/solovyev/android/calculator/messages.properties deleted file mode 100644 index e6534912..00000000 --- a/calculatorpp-core/src/main/resources/org/solovyev/android/calculator/messages.properties +++ /dev/null @@ -1,8 +0,0 @@ -msg_1=Arithmetic error occurred: {0} -msg_2=Too complex expression -msg_3=Too long execution time - check the expression -msg_4=Evaluation was cancelled -msg_5=No parameters are specified for function: {0} -msg_6=Infinite loop is detected in expression - -syntax_error=Error \ No newline at end of file diff --git a/calculatorpp-service/pom.xml b/calculatorpp-service/pom.xml index 220ae027..7696378b 100644 --- a/calculatorpp-service/pom.xml +++ b/calculatorpp-service/pom.xml @@ -22,6 +22,7 @@ com.intellij annotations + 7.0.3 diff --git a/calculatorpp/pom.xml b/calculatorpp/pom.xml index 82523499..f94bc176 100644 --- a/calculatorpp/pom.xml +++ b/calculatorpp/pom.xml @@ -19,13 +19,6 @@ - - - org.solovyev.android - calculatorpp-core - 1.3.1 - - org.solovyev common-core @@ -82,6 +75,13 @@ org.solovyev jscl + 0.0.2 + + + xercesImpl + xerces + + @@ -92,6 +92,13 @@ provided + + junit + junit + 4.8.2 + test + + net.sf.opencsv opencsv @@ -102,6 +109,17 @@ org.simpleframework simple-xml + 2.6.1 + + + stax-api + stax + + + xpp3 + xpp3 + + @@ -129,15 +147,10 @@ 11.0.2 - - junit - junit - test - - com.intellij annotations + 7.0.3 diff --git a/calculatorpp/res/layout/calc_display.xml b/calculatorpp/res/layout/calc_display.xml index c44067dd..e8c7288e 100644 --- a/calculatorpp/res/layout/calc_display.xml +++ b/calculatorpp/res/layout/calc_display.xml @@ -1,16 +1,16 @@ - - - - - + + + + \ No newline at end of file diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/Unit.java b/calculatorpp/src/main/java/org/solovyev/android/Unit.java similarity index 80% rename from calculatorpp-core/src/main/java/org/solovyev/math/units/Unit.java rename to calculatorpp/src/main/java/org/solovyev/android/Unit.java index 23921ea8..d909f67c 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/math/units/Unit.java +++ b/calculatorpp/src/main/java/org/solovyev/android/Unit.java @@ -1,4 +1,4 @@ -package org.solovyev.math.units; +package org.solovyev.android; import org.jetbrains.annotations.NotNull; diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitConverter.java b/calculatorpp/src/main/java/org/solovyev/android/UnitConverter.java similarity index 92% rename from calculatorpp-core/src/main/java/org/solovyev/math/units/UnitConverter.java rename to calculatorpp/src/main/java/org/solovyev/android/UnitConverter.java index 2d56bebd..56782cb3 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitConverter.java +++ b/calculatorpp/src/main/java/org/solovyev/android/UnitConverter.java @@ -1,4 +1,4 @@ -package org.solovyev.math.units; +package org.solovyev.android; import org.jetbrains.annotations.NotNull; diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitImpl.java b/calculatorpp/src/main/java/org/solovyev/android/UnitImpl.java similarity index 90% rename from calculatorpp-core/src/main/java/org/solovyev/math/units/UnitImpl.java rename to calculatorpp/src/main/java/org/solovyev/android/UnitImpl.java index 647e0c6f..a34ec36f 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitImpl.java +++ b/calculatorpp/src/main/java/org/solovyev/android/UnitImpl.java @@ -1,4 +1,4 @@ -package org.solovyev.math.units; +package org.solovyev.android; import org.jetbrains.annotations.NotNull; diff --git a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitType.java b/calculatorpp/src/main/java/org/solovyev/android/UnitType.java similarity index 81% rename from calculatorpp-core/src/main/java/org/solovyev/math/units/UnitType.java rename to calculatorpp/src/main/java/org/solovyev/android/UnitType.java index 457442c2..2a84f6a5 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/math/units/UnitType.java +++ b/calculatorpp/src/main/java/org/solovyev/android/UnitType.java @@ -1,4 +1,4 @@ -package org.solovyev.math.units; +package org.solovyev.android; import org.jetbrains.annotations.NotNull; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java index 4abf638d..90f0798d 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidNumeralBase.java @@ -3,10 +3,10 @@ package org.solovyev.android.calculator; import android.app.Activity; import jscl.NumeralBase; import org.jetbrains.annotations.NotNull; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; +import org.solovyev.android.Unit; +import org.solovyev.android.UnitConverter; +import org.solovyev.android.UnitImpl; +import org.solovyev.android.UnitType; import org.solovyev.android.view.drag.DirectionDragButton; import org.solovyev.android.view.drag.DragDirection; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java index d7a3c0c3..608a3aa4 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java @@ -32,7 +32,7 @@ import org.solovyev.android.AndroidUtils; import org.solovyev.android.FontSizeAdjuster; import org.solovyev.android.LocalBinder; import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity; -import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl; +import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.view.AngleUnitsButton; @@ -136,7 +136,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE); - AndroidCalculatorHistoryImpl.instance.load(this, preferences); + CalculatorHistory.instance.load(this, preferences); calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance); dpclRegister.clear(); diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java index 73a5cca1..c9d1de5a 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java @@ -46,8 +46,6 @@ public class CalculatorApplication extends android.app.Application { public void onCreate() { super.onCreate(); - CalculatorLocatorImpl.getInstance().setCalculatorEngine(CalculatorEngine.instance); - AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() { @Override diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java similarity index 52% rename from calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java index 59b68e21..13c8c9d9 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java @@ -15,9 +15,12 @@ import jscl.math.Generic; import jscl.math.function.Constant; import jscl.math.function.IConstant; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.TextProcessor; +import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.android.calculator.view.UnitConverterViewBuilder; @@ -35,9 +38,9 @@ import java.util.Set; * Date: 9/17/11 * Time: 10:58 PM */ -public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { +public class CalculatorDisplay extends AutoResizeTextView implements ICalculatorDisplay{ - private static enum ConversionMenuItem implements AMenuItem { + private static enum ConversionMenuItem implements AMenuItem { convert_to_bin(NumeralBase.bin), convert_to_dec(NumeralBase.dec), convert_to_hex(NumeralBase.hex); @@ -70,27 +73,23 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements } @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { final NumeralBase fromNumeralBase = CalculatorEngine.instance.getEngine().getNumeralBase(); - final Generic lastResult = CalculatorLocatorImpl.getInstance().getCalculatorDisplay().getViewState().getResult(); + String to; + try { + to = convert(data.getGenericResult()); - if (lastResult != null) { - String to; - try { - to = convert(lastResult); - - // add prefix - if (fromNumeralBase != toNumeralBase) { - to = toNumeralBase.getJsclPrefix() + to; - } - } catch (UnitConverterViewBuilder.ConversionException e) { - to = context.getString(R.string.c_error); + // add prefix + if (fromNumeralBase != toNumeralBase) { + to = toNumeralBase.getJsclPrefix() + to; } - - data.setText(to); - //data.redraw(); + } catch (UnitConverterViewBuilder.ConversionException e) { + to = context.getString(R.string.c_error); } + + data.setText(to); + data.redraw(); } @NotNull @@ -114,18 +113,18 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements } } - public static enum MenuItem implements LabeledMenuItem { + public static enum MenuItem implements LabeledMenuItem { copy(R.string.c_copy) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { CalculatorModel.copyResult(context, data); } }, convert_to_bin(R.string.convert_to_bin) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_bin.onClick(data, context); } @@ -137,7 +136,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements convert_to_dec(R.string.convert_to_dec) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_dec.onClick(data, context); } @@ -149,7 +148,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements convert_to_hex(R.string.convert_to_hex) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { ConversionMenuItem.convert_to_hex.onClick(data, context); } @@ -161,11 +160,8 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements convert(R.string.c_convert) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { - final Generic result = data.getState().getResult(); - if (result != null) { - new NumeralBaseConverterDialog(result.toString()).show(context); - } + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { + new NumeralBaseConverterDialog(data.getGenericResult().toString()).show(context); } @Override @@ -174,10 +170,10 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements } }, - plot(R.string.c_plot) { + plot(R.string.c_plot) { @Override - public void onClick(@NotNull CalculatorDisplayView data, @NotNull Context context) { - final Generic generic = data.getState().getResult(); + public void onClick(@NotNull CalculatorDisplay data, @NotNull Context context) { + final Generic generic = data.getGenericResult(); assert generic != null; final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); @@ -185,18 +181,18 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorActivityLauncher.plotGraph(context, generic, constant); } - @Override - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - boolean result = false; + @Override + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + boolean result = false; - if (operation == JsclOperation.simplify) { + if (operation == JsclOperation.simplify) { if (getNotSystemConstants(generic).size() == 1) { - result = true; - } - } + result = true; + } + } - return result; - } + return result; + } @NotNull private Set getNotSystemConstants(@NotNull Generic generic) { @@ -213,104 +209,140 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements } }; - private final int captionId; + private final int captionId; - MenuItem(int captionId) { - this.captionId = captionId; - } + MenuItem(int captionId) { + this.captionId = captionId; + } - public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) { - //noinspection ConstantConditions - return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation()); - } + public final boolean isItemVisible(@NotNull CalculatorDisplay display) { + //noinspection ConstantConditions + return display.isValid() && display.getGenericResult() != null && isItemVisibleFor(display.getGenericResult(), display.getJsclOperation()); + } - protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { - return true; - } + protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { + return true; + } - @NotNull - @Override - public String getCaption(@NotNull Context context) { - return context.getString(captionId); - } - } + @NotNull + @Override + public String getCaption(@NotNull Context context) { + return context.getString(captionId); + } + } - @NotNull - private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance(); + private boolean valid = true; - @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); + @Nullable + private String errorMessage; - public AndroidCalculatorDisplayView(Context context) { - super(context); - } + @NotNull + private JsclOperation jsclOperation = JsclOperation.numeric; - public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) { - super(context, attrs); - } + @NotNull + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); - public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } + @Nullable + private Generic genericResult; - public boolean isValid() { - return this.state.isValid(); - } + public CalculatorDisplay(Context context) { + super(context); + } + public CalculatorDisplay(Context context, AttributeSet attrs) { + super(context, attrs); + } - @Override - public void setState(@NotNull CalculatorDisplayViewState state) { - this.state = state; - if ( state.isValid() ) { - setTextColor(getResources().getColor(R.color.default_text_color)); - setText(state.getStringResult()); - } else { - setTextColor(getResources().getColor(R.color.display_error_text_color)); - setText(state.getErrorMessage()); - } - } + public CalculatorDisplay(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } - @NotNull - @Override - public CalculatorDisplayViewState getState() { - return this.state; - } + @Override + public boolean isValid() { + return valid; + } - @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - } + @Override + public void setValid(boolean valid) { + this.valid = valid; + if (valid) { + errorMessage = null; + setTextColor(getResources().getColor(R.color.default_text_color)); + } else { + setTextColor(getResources().getColor(R.color.display_error_text_color)); + } + } - public synchronized void redraw() { - if (isValid()) { - String text = getText().toString(); + @Override + @Nullable + public String getErrorMessage() { + return errorMessage; + } - Log.d(this.getClass().getName(), text); + @Override + public void setErrorMessage(@Nullable String errorMessage) { + this.errorMessage = errorMessage; + } - try { - TextHighlighter.Result result = textHighlighter.process(text); - text = result.toString(); - } catch (CalculatorParseException e) { - Log.e(this.getClass().getName(), e.getMessage(), e); - } + @Override + public void setJsclOperation(@NotNull JsclOperation jsclOperation) { + this.jsclOperation = jsclOperation; + } - Log.d(this.getClass().getName(), text); - super.setText(Html.fromHtml(text), BufferType.EDITABLE); - } + @Override + @NotNull + public JsclOperation getJsclOperation() { + return jsclOperation; + } - // todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize()) - setAddEllipsis(false); - setMinTextSize(10); - resizeText(); - } + @Override + public void setText(CharSequence text, BufferType type) { + super.setText(text, type); - @Override - public int getSelection() { - return this.getSelectionStart(); - } + setValid(true); + } - @Override - public void setSelection(int selection) { - // not supported by TextView - } + public synchronized void redraw() { + if (isValid()) { + String text = getText().toString(); + + Log.d(this.getClass().getName(), text); + + try { + TextHighlighter.Result result = textHighlighter.process(text); + text = result.toString(); + } catch (CalculatorParseException e) { + Log.e(this.getClass().getName(), e.getMessage(), e); + } + + Log.d(this.getClass().getName(), text); + super.setText(Html.fromHtml(text), BufferType.EDITABLE); + } + + // todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize()) + setAddEllipsis(false); + setMinTextSize(10); + resizeText(); + } + + @Override + public void setGenericResult(@Nullable Generic genericResult) { + this.genericResult = genericResult; + } + + @Override + @Nullable + public Generic getGenericResult() { + return genericResult; + } + + @Override + public int getSelection() { + return this.getSelectionStart(); + } + + @Override + public void setSelection(int selection) { + // not supported by TextView + } } diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java index 3f9b20c9..a2e0f910 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java @@ -16,7 +16,8 @@ import android.view.ContextMenu; import android.widget.EditText; import org.jetbrains.annotations.NotNull; import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.view.TextHighlighter; import org.solovyev.common.collections.CollectionsUtils; diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEngineControl.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEngineControl.java similarity index 100% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEngineControl.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEngineControl.java diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java index d459f15a..387a8ff2 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorModel.java @@ -20,12 +20,14 @@ import android.widget.Toast; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.CursorControl; -import org.solovyev.android.calculator.history.AndroidCalculatorHistoryImpl; +import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.TextViewEditorAdapter; import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.calculator.model.CalculatorEvalException; +import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.android.history.HistoryControl; import org.solovyev.android.menu.AMenuBuilder; import org.solovyev.android.menu.MenuImpl; @@ -53,7 +55,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl 0) { - display.setText(result.getStringResult()); + display.setText(result.getResult()); } else { display.setText(""); } - display.setJsclOperation(result.getOperation()); - display.setGenericResult(result.getResult()); + display.setJsclOperation(result.getUserOperation()); + display.setGenericResult(result.getGenericResult()); } catch (CalculatorParseException e) { handleEvaluationException(expression, display, operation, e); } catch (CalculatorEvalException e) { @@ -256,7 +257,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl filteredMenuItems = new ArrayList(AndroidCalculatorDisplayView.MenuItem.values().length); - for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) { - if (menuItem.isItemVisible(displayViewState)) { + if (cd.isValid()) { + final List filteredMenuItems = new ArrayList(CalculatorDisplay.MenuItem.values().length); + for (CalculatorDisplay.MenuItem menuItem : CalculatorDisplay.MenuItem.values()) { + if (menuItem.isItemVisible(cd)) { filteredMenuItems.add(menuItem); } } @@ -401,7 +400,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl() { + if ( CollectionsUtils.contains(historyState, CalculatorHistory.instance.getSavedHistory(), new Equalizer() { @Override public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) { return first != null && second != null && diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java similarity index 91% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java index 633d8a7f..fffc09b4 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryState.java @@ -6,6 +6,7 @@ package org.solovyev.android.calculator.history; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.simpleframework.xml.Element; import org.simpleframework.xml.Transient; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java deleted file mode 100644 index 2f4dc4b4..00000000 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.solovyev.android.calculator.history; - -import android.content.Context; -import android.content.SharedPreferences; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:07 - */ -public interface AndroidCalculatorHistory extends CalculatorHistory { - - void load(@Nullable Context context, @Nullable SharedPreferences preferences); - - void save(@NotNull Context context); -} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistoryImpl.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistoryImpl.java deleted file mode 100644 index b5cba95f..00000000 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistoryImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - * or visit http://se.solovyev.org - */ - -package org.solovyev.android.calculator.history; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.R; -import org.solovyev.common.history.HistoryAction; - -import java.util.List; - -/** - * User: serso - * Date: 10/9/11 - * Time: 6:35 PM - */ -public enum AndroidCalculatorHistoryImpl implements AndroidCalculatorHistory { - - instance; - - @NotNull - private final CalculatorHistoryImpl calculatorHistory = new CalculatorHistoryImpl(); - - @Override - public void load(@Nullable Context context, @Nullable SharedPreferences preferences) { - if (context != null && preferences != null) { - final String value = preferences.getString(context.getString(R.string.p_calc_history), null); - calculatorHistory.fromXml(value); - } - } - - @Override - public void save(@NotNull Context context) { - final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - final SharedPreferences.Editor editor = settings.edit(); - - editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml()); - - editor.commit(); - } - - public void clearSavedHistory(@NotNull Context context) { - calculatorHistory.clearSavedHistory(); - save(context); - } - - public void removeSavedHistory(@NotNull CalculatorHistoryState historyState, @NotNull Context context) { - historyState.setSaved(false); - calculatorHistory.removeSavedHistory(historyState); - save(context); - } - - @Override - public boolean isEmpty() { - return calculatorHistory.isEmpty(); - } - - @Override - public CalculatorHistoryState getLastHistoryState() { - return calculatorHistory.getLastHistoryState(); - } - - @Override - public boolean isUndoAvailable() { - return calculatorHistory.isUndoAvailable(); - } - - @Override - public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { - return calculatorHistory.undo(currentState); - } - - @Override - public boolean isRedoAvailable() { - return calculatorHistory.isRedoAvailable(); - } - - @Override - public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { - return calculatorHistory.redo(currentState); - } - - @Override - public boolean isActionAvailable(@NotNull HistoryAction historyAction) { - return calculatorHistory.isActionAvailable(historyAction); - } - - @Override - public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { - return calculatorHistory.doAction(historyAction, currentState); - } - - @Override - public void addState(@Nullable CalculatorHistoryState currentState) { - calculatorHistory.addState(currentState); - } - - @NotNull - @Override - public List getStates() { - return calculatorHistory.getStates(); - } - - @Override - public void clear() { - calculatorHistory.clear(); - } - - @NotNull - public List getSavedHistory() { - return calculatorHistory.getSavedHistory(); - } - - @NotNull - public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { - return calculatorHistory.addSavedState(historyState); - } - - @Override - public void fromXml(@NotNull String xml) { - calculatorHistory.fromXml(xml); - } - - @Override - public String toXml() { - return calculatorHistory.toXml(); - } - - @Override - public void clearSavedHistory() { - calculatorHistory.clearSavedHistory(); - } - - @Override - public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { - calculatorHistory.removeSavedHistory(historyState); - } -} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java similarity index 68% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java index c8c37c41..b637e901 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorDisplayHistoryState.java @@ -1,144 +1,138 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator.history; - -import jscl.math.Generic; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Root; -import org.simpleframework.xml.Transient; -import org.solovyev.android.calculator.CalculatorDisplay; -import org.solovyev.android.calculator.CalculatorDisplayViewState; -import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.text.StringUtils; - -/** - * User: serso - * Date: 9/17/11 - * Time: 11:05 PM - */ - -@Root -public class CalculatorDisplayHistoryState implements Cloneable { - - @Transient - private boolean valid = true; - - @Transient - @Nullable - private String errorMessage = null; - - @Element - @NotNull - private EditorHistoryState editorState; - - @Element - @NotNull - private JsclOperation jsclOperation; - - @Transient - @Nullable - private Generic genericResult; - - private CalculatorDisplayHistoryState() { - // for xml - } - - @NotNull - public static CalculatorDisplayHistoryState newInstance(@NotNull CalculatorDisplay display) { - final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState(); - - result.editorState = EditorHistoryState.newInstance(display.getViewState()); - - final CalculatorDisplayViewState displayViewState = display.getViewState(); - - result.valid = displayViewState.isValid(); - result.jsclOperation = displayViewState.getOperation(); - result.genericResult = displayViewState.getResult(); - result.errorMessage = displayViewState.getErrorMessage(); - - return result; - } - - public void setValuesFromHistory(@NotNull CalculatorDisplay display) { - if ( this.isValid() ) { - display.setViewState(CalculatorDisplayViewStateImpl.newValidState(this.getJsclOperation(), this.getGenericResult(), StringUtils.getNotEmpty(this.getEditorState().getText(), ""), this.getEditorState().getCursorPosition())); - } else { - display.setViewState(CalculatorDisplayViewStateImpl.newErrorState(this.getJsclOperation(), StringUtils.getNotEmpty(this.getErrorMessage(), ""))); - } - } - - - public boolean isValid() { - return valid; - } - - @NotNull - public EditorHistoryState getEditorState() { - return editorState; - } - - @NotNull - public JsclOperation getJsclOperation() { - return jsclOperation; - } - - @Nullable - public String getErrorMessage() { - return errorMessage; - } - - @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; - - CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o; - - if (!editorState.equals(that.editorState)) return false; - if (jsclOperation != that.jsclOperation) return false; - - return true; - } - - @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 - protected CalculatorDisplayHistoryState clone() { - try { - final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone(); - - clone.editorState = this.editorState.clone(); - - return clone; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator.history; + +import jscl.math.Generic; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.Root; +import org.simpleframework.xml.Transient; +import org.solovyev.android.calculator.ICalculatorDisplay; +import org.solovyev.android.calculator.jscl.JsclOperation; + +/** + * User: serso + * Date: 9/17/11 + * Time: 11:05 PM + */ + +@Root +public class CalculatorDisplayHistoryState implements Cloneable { + + @Transient + private boolean valid = true; + + @Transient + @Nullable + private String errorMessage = null; + + @Element + @NotNull + private EditorHistoryState editorState; + + @Element + @NotNull + private JsclOperation jsclOperation; + + @Transient + @Nullable + private Generic genericResult; + + private CalculatorDisplayHistoryState() { + // for xml + } + + @NotNull + public static CalculatorDisplayHistoryState newInstance(@NotNull ICalculatorDisplay display) { + final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState(); + + result.editorState = EditorHistoryState.newInstance(display); + result.valid = display.isValid(); + result.jsclOperation = display.getJsclOperation(); + result.genericResult = display.getGenericResult(); + result.errorMessage = display.getErrorMessage(); + + return result; + } + + public void setValuesFromHistory(@NotNull ICalculatorDisplay display) { + this.getEditorState().setValuesFromHistory(display); + display.setValid(this.isValid()); + display.setErrorMessage(this.getErrorMessage()); + display.setJsclOperation(this.getJsclOperation()); + display.setGenericResult(this.getGenericResult()); + } + + + public boolean isValid() { + return valid; + } + + @NotNull + public EditorHistoryState getEditorState() { + return editorState; + } + + @NotNull + public JsclOperation getJsclOperation() { + return jsclOperation; + } + + @Nullable + public String getErrorMessage() { + return errorMessage; + } + + @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; + + CalculatorDisplayHistoryState that = (CalculatorDisplayHistoryState) o; + + if (!editorState.equals(that.editorState)) return false; + if (jsclOperation != that.jsclOperation) return false; + + return true; + } + + @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 + protected CalculatorDisplayHistoryState clone() { + try { + final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone(); + + clone.editorState = this.editorState.clone(); + + return clone; + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java new file mode 100644 index 00000000..c6ec0e08 --- /dev/null +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + * or visit http://se.solovyev.org + */ + +package org.solovyev.android.calculator.history; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.R; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.history.HistoryHelper; +import org.solovyev.common.history.SimpleHistoryHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * User: serso + * Date: 10/9/11 + * Time: 6:35 PM + */ +public enum CalculatorHistory implements HistoryHelper { + + instance; + + // todo serso: not synchronized + private int counter = 0; + + @NotNull + private final HistoryHelper history = new SimpleHistoryHelper(); + + @NotNull + private final List savedHistory = new ArrayList (); + + @Override + public boolean isEmpty() { + return this.history.isEmpty(); + } + + @Override + public CalculatorHistoryState getLastHistoryState() { + return this.history.getLastHistoryState(); + } + + @Override + public boolean isUndoAvailable() { + return history.isUndoAvailable(); + } + + @Override + public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { + return history.undo(currentState); + } + + @Override + public boolean isRedoAvailable() { + return history.isRedoAvailable(); + } + + @Override + public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { + return history.redo(currentState); + } + + @Override + public boolean isActionAvailable(@NotNull HistoryAction historyAction) { + return history.isActionAvailable(historyAction); + } + + @Override + public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { + return history.doAction(historyAction, currentState); + } + + @Override + public void addState(@Nullable CalculatorHistoryState currentState) { + history.addState(currentState); + } + + @NotNull + @Override + public List getStates() { + return history.getStates(); + } + + @Override + public void clear() { + this.history.clear(); + } + + public void load(@Nullable Context context, @Nullable SharedPreferences preferences) { + if (context != null && preferences != null) { + final String value = preferences.getString(context.getString(R.string.p_calc_history), null); + this.savedHistory.clear(); + HistoryUtils.fromXml(value, this.savedHistory); + for (CalculatorHistoryState historyState : savedHistory) { + historyState.setSaved(true); + historyState.setId(counter++); + } + } + } + + public void save(@NotNull Context context) { + final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + final SharedPreferences.Editor editor = settings.edit(); + + editor.putString(context.getString(R.string.p_calc_history), HistoryUtils.toXml(this.savedHistory)); + + editor.commit(); + } + + @NotNull + public List getSavedHistory() { + return Collections.unmodifiableList(savedHistory); + } + + @NotNull + public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { + if (historyState.isSaved()) { + return historyState; + } else { + final CalculatorHistoryState savedState = historyState.clone(); + + savedState.setId(counter++); + savedState.setSaved(true); + + savedHistory.add(savedState); + + return savedState; + } + } + + public void clearSavedHistory(@NotNull Context context) { + this.savedHistory.clear(); + save(context); + } + + public void removeSavedHistory(@NotNull CalculatorHistoryState historyState, @NotNull Context context) { + historyState.setSaved(false); + this.savedHistory.remove(historyState); + save(context); + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java similarity index 91% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java index f866596a..b226390a 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryState.java @@ -1,111 +1,110 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Root; -import org.solovyev.android.calculator.CalculatorDisplay; -import org.solovyev.android.calculator.Editor; - -/** - * User: serso - * Date: 9/11/11 - * Time: 12:16 AM - */ - -@Root -public class CalculatorHistoryState extends AbstractHistoryState { - - @Element - @NotNull - private EditorHistoryState editorState; - - @Element - @NotNull - private CalculatorDisplayHistoryState displayState; - - private CalculatorHistoryState() { - // for xml - } - - private CalculatorHistoryState(@NotNull EditorHistoryState editorState, - @NotNull CalculatorDisplayHistoryState displayState) { - this.editorState = editorState; - this.displayState = displayState; - } - - public static CalculatorHistoryState newInstance(@NotNull Editor editor, @NotNull CalculatorDisplay display) { - final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor); - final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display); - return new CalculatorHistoryState(editorHistoryState, displayHistoryState); - } - - @NotNull - public EditorHistoryState getEditorState() { - return editorState; - } - - public void setEditorState(@NotNull EditorHistoryState editorState) { - this.editorState = editorState; - } - - @NotNull - public CalculatorDisplayHistoryState getDisplayState() { - return displayState; - } - - public void setDisplayState(@NotNull CalculatorDisplayHistoryState displayState) { - this.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; - - 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; - - 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; - } - - public void setValuesFromHistory(@NotNull Editor editor, @NotNull CalculatorDisplay display) { - this.getEditorState().setValuesFromHistory(editor); - this.getDisplayState().setValuesFromHistory(display); - } - - @Override - protected CalculatorHistoryState clone() { - final CalculatorHistoryState clone = (CalculatorHistoryState)super.clone(); - - clone.editorState = this.editorState.clone(); - clone.displayState = this.displayState.clone(); - - return clone; - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator.history; + +import org.jetbrains.annotations.NotNull; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.Root; +import org.solovyev.android.calculator.ICalculatorDisplay; + +/** + * User: serso + * Date: 9/11/11 + * Time: 12:16 AM + */ + +@Root +public class CalculatorHistoryState extends AbstractHistoryState { + + @Element + @NotNull + private EditorHistoryState editorState; + + @Element + @NotNull + private CalculatorDisplayHistoryState displayState; + + private CalculatorHistoryState() { + // for xml + } + + private CalculatorHistoryState(@NotNull EditorHistoryState editorState, + @NotNull CalculatorDisplayHistoryState displayState) { + this.editorState = editorState; + this.displayState = displayState; + } + + public static CalculatorHistoryState newInstance(@NotNull Editor editor, @NotNull ICalculatorDisplay display) { + final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor); + final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display); + return new CalculatorHistoryState(editorHistoryState, displayHistoryState); + } + + @NotNull + public EditorHistoryState getEditorState() { + return editorState; + } + + public void setEditorState(@NotNull EditorHistoryState editorState) { + this.editorState = editorState; + } + + @NotNull + public CalculatorDisplayHistoryState getDisplayState() { + return displayState; + } + + public void setDisplayState(@NotNull CalculatorDisplayHistoryState displayState) { + this.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; + + 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; + + 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; + } + + public void setValuesFromHistory(@NotNull Editor editor, @NotNull ICalculatorDisplay display) { + this.getEditorState().setValuesFromHistory(editor); + this.getDisplayState().setValuesFromHistory(display); + } + + @Override + protected CalculatorHistoryState clone() { + final CalculatorHistoryState clone = (CalculatorHistoryState)super.clone(); + + clone.editorState = this.editorState.clone(); + clone.displayState = this.displayState.clone(); + + return clone; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Editor.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/Editor.java similarity index 85% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/Editor.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/Editor.java index e2f53a0b..e7758d9d 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/Editor.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/Editor.java @@ -4,7 +4,7 @@ * or visit http://se.solovyev.org */ -package org.solovyev.android.calculator; +package org.solovyev.android.calculator.history; import org.jetbrains.annotations.Nullable; diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java similarity index 82% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java index 2ffa241b..77a228fb 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java @@ -1,99 +1,87 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Root; -import org.solovyev.android.calculator.CalculatorDisplayViewState; -import org.solovyev.android.calculator.Editor; - -@Root -public class EditorHistoryState implements Cloneable{ - - @Element - private int cursorPosition; - - @Element(required = false) - @Nullable - private String text; - - private EditorHistoryState() { - // for xml - } - - @NotNull - public static EditorHistoryState newInstance(@NotNull Editor editor) { - final EditorHistoryState result = new EditorHistoryState(); - - result.text = String.valueOf(editor.getText()); - result.cursorPosition = editor.getSelection(); - - return result; - } - - @NotNull - public static EditorHistoryState newInstance(@NotNull CalculatorDisplayViewState viewState) { - final EditorHistoryState result = new EditorHistoryState(); - - result.text = viewState.getText(); - result.cursorPosition = viewState.getSelection(); - - return result; - } - - public void setValuesFromHistory(@NotNull Editor editor) { - editor.setText(this.getText()); - editor.setSelection(this.getCursorPosition()); - } - - @Nullable - public String getText() { - return text; - } - - public int getCursorPosition() { - return cursorPosition; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof EditorHistoryState)) return false; - - EditorHistoryState that = (EditorHistoryState) o; - - if (cursorPosition != that.cursorPosition) return false; - if (text != null ? !text.equals(that.text) : that.text != null) return false; - - return true; - } - - @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 - protected EditorHistoryState clone() { - try { - return (EditorHistoryState)super.clone(); - } catch (CloneNotSupportedException e) { - throw new UnsupportedOperationException(e); - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator.history; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.Root; + +@Root +public class EditorHistoryState implements Cloneable{ + + @Element + private int cursorPosition; + + @Element(required = false) + @Nullable + private String text; + + private EditorHistoryState() { + // for xml + } + + @NotNull + public static EditorHistoryState newInstance(@NotNull Editor editor) { + final EditorHistoryState result = new EditorHistoryState(); + + result.text = String.valueOf(editor.getText()); + result.cursorPosition = editor.getSelection(); + + return result; + } + + public void setValuesFromHistory(@NotNull Editor editor) { + editor.setText(this.getText()); + editor.setSelection(this.getCursorPosition()); + } + + @Nullable + public String getText() { + return text; + } + + public int getCursorPosition() { + return cursorPosition; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EditorHistoryState)) return false; + + EditorHistoryState that = (EditorHistoryState) o; + + if (cursorPosition != that.cursorPosition) return false; + if (text != null ? !text.equals(that.text) : that.text != null) return false; + + return true; + } + + @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 + protected EditorHistoryState clone() { + try { + return (EditorHistoryState)super.clone(); + } catch (CloneNotSupportedException e) { + throw new UnsupportedOperationException(e); + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/History.java similarity index 100% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/History.java diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryActivityTab.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryActivityTab.java index 73f67340..4638a53c 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryActivityTab.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryActivityTab.java @@ -26,12 +26,12 @@ public class HistoryActivityTab extends AbstractHistoryActivity { @NotNull @Override protected List getHistoryItems() { - return new ArrayList(AndroidCalculatorHistoryImpl.instance.getStates()); + return new ArrayList(CalculatorHistory.instance.getStates()); } @Override protected void clearHistory() { - AndroidCalculatorHistoryImpl.instance.clear(); + CalculatorHistory.instance.clear(); getAdapter().clear(); } } diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java index 7cb1c859..1febb82f 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java @@ -96,7 +96,7 @@ public enum HistoryItemMenuItem implements LabeledMenuItem final CalculatorHistoryState historyState = data.getHistoryState(); if (historyState.isSaved()) { data.getAdapter().remove(historyState); - AndroidCalculatorHistoryImpl.instance.removeSavedHistory(historyState, context); + CalculatorHistory.instance.removeSavedHistory(historyState, context); Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show(); data.getAdapter().notifyDataSetChanged(); } @@ -122,14 +122,14 @@ public enum HistoryItemMenuItem implements LabeledMenuItem @Override public void onClick(DialogInterface dialog, int which) { if (save) { - final CalculatorHistoryState savedHistoryItem = AndroidCalculatorHistoryImpl.instance.addSavedState(historyState); + final CalculatorHistoryState savedHistoryItem = CalculatorHistory.instance.addSavedState(historyState); savedHistoryItem.setComment(comment.getText().toString()); - AndroidCalculatorHistoryImpl.instance.save(context); + CalculatorHistory.instance.save(context); // we don't need to add element to the adapter as adapter of another activity must be updated and not this //data.getAdapter().add(savedHistoryItem); } else { historyState.setComment(comment.getText().toString()); - AndroidCalculatorHistoryImpl.instance.save(context); + CalculatorHistory.instance.save(context); } data.getAdapter().notifyDataSetChanged(); Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show(); diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/HistoryUtils.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryUtils.java similarity index 100% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/HistoryUtils.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryUtils.java diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/SavedHistoryActivityTab.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/SavedHistoryActivityTab.java index 6113c89d..c5bc1c34 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/SavedHistoryActivityTab.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/SavedHistoryActivityTab.java @@ -26,12 +26,12 @@ public class SavedHistoryActivityTab extends AbstractHistoryActivity { @NotNull @Override protected List getHistoryItems() { - return new ArrayList(AndroidCalculatorHistoryImpl.instance.getSavedHistory()); + return new ArrayList(CalculatorHistory.instance.getSavedHistory()); } @Override protected void clearHistory() { - AndroidCalculatorHistoryImpl.instance.clearSavedHistory(this); + CalculatorHistory.instance.clearSavedHistory(this); getAdapter().clear(); } } diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/TextViewEditorAdapter.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/TextViewEditorAdapter.java index 35207b07..42b513a2 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/TextViewEditorAdapter.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/TextViewEditorAdapter.java @@ -10,7 +10,6 @@ import android.widget.EditText; import android.widget.TextView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.Editor; /** * User: serso diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java similarity index 80% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java index 2251e5b8..b664c9ff 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/FromJsclNumericTextProcessor.java @@ -8,8 +8,8 @@ package org.solovyev.android.calculator.jscl; import jscl.math.Generic; import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.TextProcessor; /** * User: serso diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java similarity index 55% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java index 978964b7..2ba3d902 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/jscl/JsclOperation.java @@ -9,10 +9,10 @@ package org.solovyev.android.calculator.jscl; import jscl.math.Generic; import jscl.text.ParseException; import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.text.DummyTextProcessor; -import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor; -import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.calculator.model.DummyTextProcessor; +import org.solovyev.android.calculator.model.FromJsclSimplifyTextProcessor; +import org.solovyev.android.calculator.model.TextProcessor; public enum JsclOperation { @@ -42,11 +42,11 @@ public enum JsclOperation { public final String evaluate(@NotNull String expression) throws ParseException { switch (this) { case simplify: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().simplify(expression); + return CalculatorEngine.instance.getEngine().simplify(expression); case elementary: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().elementary(expression); + return CalculatorEngine.instance.getEngine().elementary(expression); case numeric: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().evaluate(expression); + return CalculatorEngine.instance.getEngine().evaluate(expression); default: throw new UnsupportedOperationException(); } @@ -56,11 +56,11 @@ public enum JsclOperation { public final Generic evaluateGeneric(@NotNull String expression) throws ParseException { switch (this) { case simplify: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().simplifyGeneric(expression); + return CalculatorEngine.instance.getEngine().simplifyGeneric(expression); case elementary: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().elementaryGeneric(expression); + return CalculatorEngine.instance.getEngine().elementaryGeneric(expression); case numeric: - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getEngine().evaluateGeneric(expression); + return CalculatorEngine.instance.getEngine().evaluateGeneric(expression); default: throw new UnsupportedOperationException(); } diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/math/MathType.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/math/MathType.java similarity index 91% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/math/MathType.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/math/MathType.java index 549ae9fd..8efc1f1d 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/math/MathType.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/math/MathType.java @@ -10,10 +10,10 @@ import jscl.NumeralBase; import jscl.math.function.Constants; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorLocatorImpl; import org.solovyev.common.JPredicate; import org.solovyev.common.StartsWithFinder; -import org.solovyev.android.calculator.CalculatorParseException; +import org.solovyev.android.calculator.model.CalculatorEngine; +import org.solovyev.android.calculator.model.CalculatorParseException; import org.solovyev.common.collections.CollectionsUtils; import java.util.*; @@ -26,8 +26,11 @@ public enum MathType { private final List tokens = new ArrayList(10); { for (NumeralBase numeralBase : NumeralBase.values()) { - tokens.add(numeralBase.getJsclPrefix()); - } + final String jsclPrefix = numeralBase.getJsclPrefix(); + if (jsclPrefix != null) { + tokens.add(jsclPrefix); + } + } } @NotNull @@ -57,7 +60,7 @@ public enum MathType { @NotNull @Override public List getTokens() { - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getPostfixFunctionsRegistry().getNames(); + return CalculatorEngine.instance.getPostfixFunctionsRegistry().getNames(); } }, @@ -101,7 +104,7 @@ public enum MathType { @NotNull @Override public List getTokens() { - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getFunctionsRegistry().getNames(); + return CalculatorEngine.instance.getFunctionsRegistry().getNames(); } }, @@ -109,7 +112,7 @@ public enum MathType { @NotNull @Override public List getTokens() { - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getOperatorsRegistry().getNames(); + return CalculatorEngine.instance.getOperatorsRegistry().getNames(); } }, @@ -117,7 +120,7 @@ public enum MathType { @NotNull @Override public List getTokens() { - return CalculatorLocatorImpl.getInstance().getCalculatorEngine().getVarsRegistry().getNames(); + return CalculatorEngine.instance.getVarsRegistry().getNames(); } @Override diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/AbstractNumberBuilder.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AbstractNumberBuilder.java similarity index 95% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/AbstractNumberBuilder.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/model/AbstractNumberBuilder.java index a95e6703..a66cd44f 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/AbstractNumberBuilder.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AbstractNumberBuilder.java @@ -4,7 +4,7 @@ * or visit http://se.solovyev.org */ -package org.solovyev.android.calculator; +package org.solovyev.android.calculator.model; import jscl.MathEngine; import jscl.NumeralBase; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java index 4dfa07f0..68bcc9b8 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java @@ -1,404 +1,425 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator.model; - -import android.content.Context; -import android.content.SharedPreferences; -import jscl.*; -import jscl.math.Generic; -import jscl.math.function.Function; -import jscl.math.function.IConstant; -import jscl.math.operator.Operator; -import jscl.text.ParseInterruptedException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.android.msg.AndroidMessage; -import org.solovyev.android.prefs.BooleanPreference; -import org.solovyev.android.prefs.Preference; -import org.solovyev.android.prefs.StringPreference; -import org.solovyev.common.MutableObject; -import org.solovyev.common.msg.MessageRegistry; -import org.solovyev.common.msg.MessageType; -import org.solovyev.common.text.EnumMapper; -import org.solovyev.common.text.NumberMapper; -import org.solovyev.common.text.StringUtils; - -import java.text.DecimalFormatSymbols; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * User: serso - * Date: 9/12/11 - * Time: 11:38 PM - */ - -public enum CalculatorEngine implements JCalculatorEngine { - - instance; - - private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator"; - - private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign"; - private static final String MULTIPLICATION_SIGN_DEFAULT = "×"; - - private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time"; - private static final String MAX_CALCULATION_TIME_DEFAULT = "5"; - - private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation"; - private static final boolean SCIENCE_NOTATION_DEFAULT = false; - - private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result"; - private static final boolean ROUND_RESULT_DEFAULT = true; - - private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision"; - private static final String RESULT_PRECISION_DEFAULT = "5"; - - private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases"; - private static final String NUMERAL_BASES_DEFAULT = "dec"; - - private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units"; - private static final String ANGLE_UNITS_DEFAULT = "deg"; - - public static class Preferences { - public static final Preference groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT); - public static final Preference multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT); - public static final Preference precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper(Integer.class)); - public static final Preference roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT); - public static final Preference numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class)); - public static final Preference angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class)); - public static final Preference scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT); - public static final Preference maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper(Integer.class)); - - private static final List preferenceKeys = new ArrayList(); - - static { - preferenceKeys.add(groupingSeparator.getKey()); - preferenceKeys.add(multiplicationSign.getKey()); - preferenceKeys.add(precision.getKey()); - preferenceKeys.add(roundResult.getKey()); - preferenceKeys.add(numeralBase.getKey()); - preferenceKeys.add(angleUnit.getKey()); - preferenceKeys.add(scienceNotation.getKey()); - preferenceKeys.add(maxCalculationTime.getKey()); - } - - @NotNull - public static List getPreferenceKeys() { - return Collections.unmodifiableList(preferenceKeys); - } - } - - @NotNull - private final Object lock = new Object(); - - @NotNull - private MathEngine engine = JsclMathEngine.instance; - - @NotNull - public final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); - - @NotNull - private final AndroidMathRegistry varsRegistry = new AndroidVarsRegistryImpl(engine.getConstantsRegistry()); - - @NotNull - private final AndroidMathRegistry functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry()); - - @NotNull - private final AndroidMathRegistry operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry()); - - private final AndroidMathRegistry postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry()); - - @Nullable - private ThreadKiller threadKiller = new AndroidThreadKiller(); - - // calculation thread timeout in seconds, after timeout thread would be interrupted - private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT); - - @NotNull - private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT; - - CalculatorEngine() { - this.engine.setRoundResult(true); - this.engine.setUseGroupingSeparator(true); - } - - @Override - @NotNull - public String getMultiplicationSign() { - return multiplicationSign; - } - - public void setMultiplicationSign(@NotNull String multiplicationSign) { - this.multiplicationSign = multiplicationSign; - } - - public CalculatorOutput evaluate(@NotNull JsclOperation operation, - @NotNull String expression) throws CalculatorParseException, CalculatorEvalException { - return evaluate(operation, expression, null); - } - - public CalculatorOutput evaluate(@NotNull final JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException { - synchronized (lock) { - final StringBuilder sb = new StringBuilder(); - - final PreparedExpression preparedExpression = preprocessor.process(expression); - sb.append(preparedExpression); - - //Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preparedExpression); - /*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) { - operation = JsclOperation.simplify; - - if (mr != null) { - final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter() { - @Override - public String formatValue(@Nullable Var var) throws IllegalArgumentException { - return var != null ? var.getName() : ""; - } - }); - - mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars)); - } - }*/ - - final String jsclExpression = sb.toString(); - - final MutableObject calculationResult = new MutableObject(null); - final MutableObject parseException = new MutableObject(null); - final MutableObject evalException = new MutableObject(null); - final MutableObject calculationThread = new MutableObject(null); - - final CountDownLatch latch = new CountDownLatch(1); - - new Thread(new Runnable() { - @Override - public void run() { - final Thread thread = Thread.currentThread(); - try { - //Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName()); - //System.out.println(jsclExpression); - calculationThread.setObject(thread); - final Generic genericResult = operation.evaluateGeneric(jsclExpression); - - // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) - genericResult.toString(); - - calculationResult.setObject(genericResult); - } catch (AbstractJsclArithmeticException e) { - evalException.setObject(new CalculatorEvalException(e, e, jsclExpression)); - } catch (ArithmeticException e) { - //System.out.println(e.getMessage()); - final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_1, MessageType.error, CalculatorApplication.getInstance(), e.getMessage()); - parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage)); - } catch (StackOverflowError e) { - //System.out.println(StringUtils.fromStackTrace(e.getStackTrace())); - final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_2, MessageType.error, CalculatorApplication.getInstance()); - parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage)); - } catch (jscl.text.ParseException e) { - //System.out.println(e.getMessage()); - parseException.setObject(new CalculatorParseException(e)); - } catch (ParseInterruptedException e) { - //System.out.println(e.getMessage()); - // do nothing - we ourselves interrupt the calculations - } finally { - //Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName()); - calculationThread.setObject(null); - latch.countDown(); - } - } - }).start(); - - try { - //Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName()); - latch.await(timeout, TimeUnit.SECONDS); - //Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName()); - - final CalculatorParseException parseExceptionObject = parseException.getObject(); - final CalculatorEvalException evalExceptionObject = evalException.getObject(); - final Object calculationResultLocal = calculationResult.getObject(); - final Thread calculationThreadLocal = calculationThread.getObject(); - - if (calculationThreadLocal != null) { - if (threadKiller != null) { - threadKiller.killThread(calculationThreadLocal); - } - //calculationThreadLocal.stop(); - } - - if (parseExceptionObject != null || evalExceptionObject != null) { - if (operation == JsclOperation.numeric && - (preparedExpression.isExistsUndefinedVar() || (evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException))) { - return evaluate(JsclOperation.simplify, expression, mr); - } - - if (parseExceptionObject != null) { - throw parseExceptionObject; - } else { - throw evalExceptionObject; - } - } - - if (calculationResultLocal == null) { - final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_3, MessageType.error, CalculatorApplication.getInstance()); - throw new CalculatorParseException(jsclExpression, androidMessage); - } - - } catch (InterruptedException e) { - final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_4, MessageType.error, CalculatorApplication.getInstance()); - throw new CalculatorParseException(jsclExpression, androidMessage); - } - - final Generic genericResult = calculationResult.getObject(); - - return new CalculatorOutputImpl(operation.getFromProcessor().process(genericResult), operation, genericResult); - } - } - - public void setPrecision(int precision) { - this.getEngine().setPrecision(precision); - } - - public void setRoundResult(boolean roundResult) { - this.getEngine().setRoundResult(roundResult); - } - - public void init(@Nullable Context context, @Nullable SharedPreferences preferences) { - synchronized (lock) { - reset(context, preferences); - } - } - - public void reset(@Nullable Context context, @Nullable SharedPreferences preferences) { - synchronized (lock) { - softReset(context, preferences); - - varsRegistry.load(context, preferences); - functionsRegistry.load(context, preferences); - operatorsRegistry.load(context, preferences); - postfixFunctionsRegistry.load(context, preferences); - } - } - - public void softReset(@Nullable Context context, @Nullable SharedPreferences preferences) { - synchronized (lock) { - if (preferences != null) { - this.setPrecision(Preferences.precision.getPreference(preferences)); - this.setRoundResult(Preferences.roundResult.getPreference(preferences)); - this.setAngleUnits(getAngleUnitsFromPrefs(preferences)); - this.setNumeralBase(getNumeralBaseFromPrefs(preferences)); - this.setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences)); - this.setScienceNotation(Preferences.scienceNotation.getPreference(preferences)); - this.setTimeout(Preferences.maxCalculationTime.getPreference(preferences)); - - final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences); - if (StringUtils.isEmpty(groupingSeparator)) { - this.getEngine().setUseGroupingSeparator(false); - } else { - this.getEngine().setUseGroupingSeparator(true); - this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0)); - } - } - } - } - - - @NotNull - public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) { - return Preferences.numeralBase.getPreference(preferences); - } - - @NotNull - public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) { - return Preferences.angleUnit.getPreference(preferences); - } - - //for tests only - void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) { - synchronized (lock) { - this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols); - } - } - - @Override - @NotNull - public AndroidMathRegistry getVarsRegistry() { - return varsRegistry; - } - - @Override - @NotNull - public AndroidMathRegistry getFunctionsRegistry() { - return functionsRegistry; - } - - @Override - @NotNull - public AndroidMathRegistry getOperatorsRegistry() { - return operatorsRegistry; - } - - @Override - @NotNull - public AndroidMathRegistry getPostfixFunctionsRegistry() { - return postfixFunctionsRegistry; - } - - @Override - @NotNull - public MathEngine getEngine() { - return engine; - } - - // package protected for tests - void setTimeout(int timeout) { - this.timeout = timeout; - } - - public void setAngleUnits(@NotNull AngleUnit angleUnits) { - getEngine().setAngleUnits(angleUnits); - } - - public void setScienceNotation(boolean scienceNotation) { - getEngine().setScienceNotation(scienceNotation); - } - - public void setNumeralBase(@NotNull NumeralBase numeralBase) { - getEngine().setNumeralBase(numeralBase); - } - - // for tests only - void setThreadKiller(@Nullable ThreadKiller threadKiller) { - this.threadKiller = threadKiller; - } - - private static interface ThreadKiller { - void killThread(@NotNull Thread thread); - } - - private static class AndroidThreadKiller implements ThreadKiller { - @Override - public void killThread(@NotNull Thread thread) { - thread.setPriority(Thread.MIN_PRIORITY); - thread.interrupt(); - } - } - - public static class ThreadKillerImpl implements ThreadKiller { - @Override - public void killThread(@NotNull Thread thread) { - thread.setPriority(Thread.MIN_PRIORITY); - thread.stop(); - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator.model; + +import android.content.Context; +import android.content.SharedPreferences; +import jscl.*; +import jscl.math.Generic; +import jscl.math.function.Function; +import jscl.math.function.IConstant; +import jscl.math.operator.Operator; +import jscl.text.ParseInterruptedException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.CalculatorApplication; +import org.solovyev.android.calculator.R; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.prefs.BooleanPreference; +import org.solovyev.android.prefs.Preference; +import org.solovyev.android.prefs.StringPreference; +import org.solovyev.common.MutableObject; +import org.solovyev.common.msg.MessageRegistry; +import org.solovyev.common.text.EnumMapper; +import org.solovyev.common.text.NumberMapper; +import org.solovyev.common.text.StringUtils; + +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * User: serso + * Date: 9/12/11 + * Time: 11:38 PM + */ + +public enum CalculatorEngine { + + instance; + + private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator"; + + private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign"; + private static final String MULTIPLICATION_SIGN_DEFAULT = "×"; + + private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time"; + private static final String MAX_CALCULATION_TIME_DEFAULT = "5"; + + private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation"; + private static final boolean SCIENCE_NOTATION_DEFAULT = false; + + private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result"; + private static final boolean ROUND_RESULT_DEFAULT = true; + + private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision"; + private static final String RESULT_PRECISION_DEFAULT = "5"; + + private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases"; + private static final String NUMERAL_BASES_DEFAULT = "dec"; + + private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units"; + private static final String ANGLE_UNITS_DEFAULT = "deg"; + + public static class Preferences { + public static final Preference groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT); + public static final Preference multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT); + public static final Preference precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper(Integer.class)); + public static final Preference roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT); + public static final Preference numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class)); + public static final Preference angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class)); + public static final Preference scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT); + public static final Preference maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper(Integer.class)); + + private static final List preferenceKeys = new ArrayList(); + + static { + preferenceKeys.add(groupingSeparator.getKey()); + preferenceKeys.add(multiplicationSign.getKey()); + preferenceKeys.add(precision.getKey()); + preferenceKeys.add(roundResult.getKey()); + preferenceKeys.add(numeralBase.getKey()); + preferenceKeys.add(angleUnit.getKey()); + preferenceKeys.add(scienceNotation.getKey()); + preferenceKeys.add(maxCalculationTime.getKey()); + } + + @NotNull + public static List getPreferenceKeys() { + return Collections.unmodifiableList(preferenceKeys); + } + } + + @NotNull + private final Object lock = new Object(); + + @NotNull + private MathEngine engine = JsclMathEngine.instance; + + @NotNull + public final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); + + @NotNull + private final AndroidMathRegistry varsRegistry = new AndroidVarsRegistryImpl(engine.getConstantsRegistry()); + + @NotNull + private final AndroidMathRegistry functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry()); + + @NotNull + private final AndroidMathRegistry operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry()); + + private final AndroidMathRegistry postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry()); + + @Nullable + private ThreadKiller threadKiller = new AndroidThreadKiller(); + + // calculation thread timeout in seconds, after timeout thread would be interrupted + private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT); + + @NotNull + private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT; + + CalculatorEngine() { + this.engine.setRoundResult(true); + this.engine.setUseGroupingSeparator(true); + } + + @NotNull + public String getMultiplicationSign() { + return multiplicationSign; + } + + public void setMultiplicationSign(@NotNull String multiplicationSign) { + this.multiplicationSign = multiplicationSign; + } + + public static class Result { + + @NotNull + private Generic genericResult; + + @NotNull + private String result; + + @NotNull + private JsclOperation userOperation; + + public Result(@NotNull String result, @NotNull JsclOperation userOperation, @NotNull Generic genericResult) { + this.result = result; + this.userOperation = userOperation; + this.genericResult = genericResult; + } + + @NotNull + public String getResult() { + return result; + } + + @NotNull + public JsclOperation getUserOperation() { + return userOperation; + } + + @NotNull + public Generic getGenericResult() { + return genericResult; + } + } + + public Result evaluate(@NotNull JsclOperation operation, + @NotNull String expression) throws CalculatorParseException, CalculatorEvalException { + return evaluate(operation, expression, null); + } + + public Result evaluate(@NotNull final JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException { + synchronized (lock) { + final StringBuilder sb = new StringBuilder(); + + final PreparedExpression preparedExpression = preprocessor.process(expression); + sb.append(preparedExpression); + + //Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preparedExpression); + /*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) { + operation = JsclOperation.simplify; + + if (mr != null) { + final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter() { + @Override + public String formatValue(@Nullable Var var) throws IllegalArgumentException { + return var != null ? var.getName() : ""; + } + }); + + mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars)); + } + }*/ + + final String jsclExpression = sb.toString(); + + final MutableObject calculationResult = new MutableObject(null); + final MutableObject parseException = new MutableObject(null); + final MutableObject evalException = new MutableObject(null); + final MutableObject calculationThread = new MutableObject(null); + + final CountDownLatch latch = new CountDownLatch(1); + + new Thread(new Runnable() { + @Override + public void run() { + final Thread thread = Thread.currentThread(); + try { + //Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName()); + //System.out.println(jsclExpression); + calculationThread.setObject(thread); + final Generic genericResult = operation.evaluateGeneric(jsclExpression); + + // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) + genericResult.toString(); + + calculationResult.setObject(genericResult); + } catch (AbstractJsclArithmeticException e) { + evalException.setObject(new CalculatorEvalException(e, e, jsclExpression)); + } catch (ArithmeticException e) { + //System.out.println(e.getMessage()); + parseException.setObject(new CalculatorParseException(R.string.msg_1, CalculatorApplication.getInstance(), jsclExpression, e.getMessage())); + } catch (StackOverflowError e) { + //System.out.println(StringUtils.fromStackTrace(e.getStackTrace())); + parseException.setObject(new CalculatorParseException(R.string.msg_2, CalculatorApplication.getInstance(), jsclExpression)); + } catch (jscl.text.ParseException e) { + //System.out.println(e.getMessage()); + parseException.setObject(new CalculatorParseException(e)); + } catch (ParseInterruptedException e) { + //System.out.println(e.getMessage()); + // do nothing - we ourselves interrupt the calculations + } finally { + //Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName()); + calculationThread.setObject(null); + latch.countDown(); + } + } + }).start(); + + try { + //Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName()); + latch.await(timeout, TimeUnit.SECONDS); + //Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName()); + + final CalculatorParseException parseExceptionObject = parseException.getObject(); + final CalculatorEvalException evalExceptionObject = evalException.getObject(); + final Object calculationResultLocal = calculationResult.getObject(); + final Thread calculationThreadLocal = calculationThread.getObject(); + + if (calculationThreadLocal != null) { + if (threadKiller != null) { + threadKiller.killThread(calculationThreadLocal); + } + //calculationThreadLocal.stop(); + } + + if (parseExceptionObject != null || evalExceptionObject != null) { + if (operation == JsclOperation.numeric && + (preparedExpression.isExistsUndefinedVar() || (evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException))) { + return evaluate(JsclOperation.simplify, expression, mr); + } + + if (parseExceptionObject != null) { + throw parseExceptionObject; + } else { + throw evalExceptionObject; + } + } + + if (calculationResultLocal == null) { + throw new CalculatorParseException(R.string.msg_3, CalculatorApplication.getInstance(), jsclExpression); + } + + } catch (InterruptedException e) { + throw new CalculatorParseException(R.string.msg_4, CalculatorApplication.getInstance(), jsclExpression); + } + + final Generic genericResult = calculationResult.getObject(); + + return new Result(operation.getFromProcessor().process(genericResult), operation, genericResult); + } + } + + public void setPrecision(int precision) { + this.getEngine().setPrecision(precision); + } + + public void setRoundResult(boolean roundResult) { + this.getEngine().setRoundResult(roundResult); + } + + public void init(@Nullable Context context, @Nullable SharedPreferences preferences) { + synchronized (lock) { + reset(context, preferences); + } + } + + public void reset(@Nullable Context context, @Nullable SharedPreferences preferences) { + synchronized (lock) { + softReset(context, preferences); + + varsRegistry.load(context, preferences); + functionsRegistry.load(context, preferences); + operatorsRegistry.load(context, preferences); + postfixFunctionsRegistry.load(context, preferences); + } + } + + public void softReset(@Nullable Context context, @Nullable SharedPreferences preferences) { + synchronized (lock) { + if (preferences != null) { + this.setPrecision(Preferences.precision.getPreference(preferences)); + this.setRoundResult(Preferences.roundResult.getPreference(preferences)); + this.setAngleUnits(getAngleUnitsFromPrefs(preferences)); + this.setNumeralBase(getNumeralBaseFromPrefs(preferences)); + this.setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences)); + this.setScienceNotation(Preferences.scienceNotation.getPreference(preferences)); + this.setTimeout(Preferences.maxCalculationTime.getPreference(preferences)); + + final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences); + if (StringUtils.isEmpty(groupingSeparator)) { + this.getEngine().setUseGroupingSeparator(false); + } else { + this.getEngine().setUseGroupingSeparator(true); + this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0)); + } + } + } + } + + + @NotNull + public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) { + return Preferences.numeralBase.getPreference(preferences); + } + + @NotNull + public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) { + return Preferences.angleUnit.getPreference(preferences); + } + + //for tests only + void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) { + synchronized (lock) { + this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols); + } + } + + @NotNull + public AndroidMathRegistry getVarsRegistry() { + return varsRegistry; + } + + @NotNull + public AndroidMathRegistry getFunctionsRegistry() { + return functionsRegistry; + } + + @NotNull + public AndroidMathRegistry getOperatorsRegistry() { + return operatorsRegistry; + } + + @NotNull + public AndroidMathRegistry getPostfixFunctionsRegistry() { + return postfixFunctionsRegistry; + } + + @NotNull + public MathEngine getEngine() { + return engine; + } + + // package protected for tests + void setTimeout(int timeout) { + this.timeout = timeout; + } + + public void setAngleUnits(@NotNull AngleUnit angleUnits) { + getEngine().setAngleUnits(angleUnits); + } + + public void setScienceNotation(boolean scienceNotation) { + getEngine().setScienceNotation(scienceNotation); + } + + public void setNumeralBase(@NotNull NumeralBase numeralBase) { + getEngine().setNumeralBase(numeralBase); + } + + // for tests only + void setThreadKiller(@Nullable ThreadKiller threadKiller) { + this.threadKiller = threadKiller; + } + + private static interface ThreadKiller { + void killThread(@NotNull Thread thread); + } + + private static class AndroidThreadKiller implements ThreadKiller { + @Override + public void killThread(@NotNull Thread thread) { + thread.setPriority(Thread.MIN_PRIORITY); + thread.interrupt(); + } + } + + public static class ThreadKillerImpl implements ThreadKiller { + @Override + public void killThread(@NotNull Thread thread) { + thread.setPriority(Thread.MIN_PRIORITY); + thread.stop(); + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvalException.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java similarity index 89% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvalException.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java index 8aba31d2..bfaa7698 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEvalException.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java @@ -4,8 +4,9 @@ * or visit http://se.solovyev.org */ -package org.solovyev.android.calculator; +package org.solovyev.android.calculator.model; +import jscl.AbstractJsclArithmeticException; import org.jetbrains.annotations.NotNull; import org.solovyev.common.exceptions.SersoException; import org.solovyev.common.msg.Message; diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorParseException.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorParseException.java similarity index 71% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorParseException.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorParseException.java index 8ebfccf7..e164578f 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorParseException.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/CalculatorParseException.java @@ -4,10 +4,12 @@ * or visit http://se.solovyev.org */ -package org.solovyev.android.calculator; +package org.solovyev.android.calculator.model; +import android.app.Application; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.solovyev.android.msg.AndroidMessage; import org.solovyev.common.exceptions.SersoException; import org.solovyev.common.msg.Message; import org.solovyev.common.msg.MessageType; @@ -37,17 +39,14 @@ public class CalculatorParseException extends SersoException implements Message this.position = jsclParseException.getPosition(); } - public CalculatorParseException(@Nullable Integer position, - @NotNull String expression, - @NotNull Message message) { - this.message = message; + public CalculatorParseException(@NotNull Integer messageId, @NotNull Application application, @Nullable Integer position, @NotNull String expression, Object... parameters) { + this.message = new AndroidMessage(messageId, MessageType.error, application, parameters); this.expression = expression; this.position = position; } - public CalculatorParseException(@NotNull String expression, - @NotNull Message message) { - this(null, expression, message); + public CalculatorParseException(@NotNull Integer messageId, @NotNull Application application, @NotNull String expression, Object... parameters) { + this(messageId, application, null, expression, parameters); } @NotNull diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/DummyTextProcessor.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java similarity index 78% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/DummyTextProcessor.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java index 22a969c5..779a1fe8 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/DummyTextProcessor.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/DummyTextProcessor.java @@ -4,11 +4,10 @@ * or visit http://se.solovyev.org */ -package org.solovyev.android.calculator.text; +package org.solovyev.android.calculator.model; import jscl.math.Generic; import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorParseException; /** * User: serso diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/FromJsclSimplifyTextProcessor.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java similarity index 86% rename from calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/FromJsclSimplifyTextProcessor.java rename to calculatorpp/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java index 3fc4da64..2f47d1e7 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/text/FromJsclSimplifyTextProcessor.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java @@ -1,11 +1,9 @@ -package org.solovyev.android.calculator.text; +package org.solovyev.android.calculator.model; import jscl.math.Generic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorLocatorImpl; import org.solovyev.android.calculator.math.MathType; -import org.solovyev.android.calculator.CalculatorParseException; import java.util.Arrays; import java.util.List; @@ -57,7 +55,7 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor undefinedVars) throws CalculatorParseException { if (depth >= MAX_DEPTH) { - final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_6, MessageType.error, CalculatorApplication.getInstance()); - throw new CalculatorParseException(s, androidMessage); + throw new CalculatorParseException(R.string.msg_6, CalculatorApplication.getInstance(), s); } else { depth++; } diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotActivity.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotActivity.java index c38714bc..e8a29bcf 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotActivity.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/plot/CalculatorPlotActivity.java @@ -35,9 +35,9 @@ import org.achartengine.tools.ZoomListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.R; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.PreparedExpression; -import org.solovyev.android.calculator.ToJsclTextProcessor; +import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.PreparedExpression; +import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.common.MutableObject; import java.io.Serializable; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java index 78f3a0bd..4b6746a3 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/NumeralBaseConverterDialog.java @@ -6,14 +6,14 @@ import android.view.View; import android.view.WindowManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitImpl; +import org.solovyev.android.Unit; +import org.solovyev.android.UnitImpl; import org.solovyev.android.calculator.AndroidNumeralBase; import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.ToJsclTextProcessor; +import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.ToJsclTextProcessor; import org.solovyev.common.MutableObject; import org.solovyev.common.text.StringUtils; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/TextHighlighter.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/TextHighlighter.java index 0d616fcc..a0ba0a31 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/TextHighlighter.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/TextHighlighter.java @@ -9,13 +9,8 @@ package org.solovyev.android.calculator.view; import jscl.MathContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.AbstractNumberBuilder; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.LiteNumberBuilder; -import org.solovyev.android.calculator.NumberBuilder; import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.*; -import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.common.MutableObject; import java.util.HashMap; diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java index d75c7240..c4393393 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/view/UnitConverterViewBuilder.java @@ -10,10 +10,10 @@ import android.view.ViewGroup; import android.widget.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; -import org.solovyev.math.units.UnitImpl; -import org.solovyev.math.units.UnitType; +import org.solovyev.android.Unit; +import org.solovyev.android.UnitConverter; +import org.solovyev.android.UnitImpl; +import org.solovyev.android.UnitType; import org.solovyev.android.calculator.R; import org.solovyev.android.view.ViewBuilder; import org.solovyev.android.view.ViewFromLayoutBuilder; diff --git a/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java b/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java index 5ad54751..b99ff21a 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/AndroidNumeralBaseTest.java @@ -4,8 +4,6 @@ import junit.framework.Assert; import org.jetbrains.annotations.NotNull; import org.junit.Test; import org.solovyev.android.calculator.AndroidNumeralBase; -import org.solovyev.math.units.Unit; -import org.solovyev.math.units.UnitConverter; import java.util.Date; import java.util.Random; diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java index af984177..021ce608 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java @@ -12,7 +12,7 @@ import jscl.NumeralBase; import junit.framework.Assert; import org.junit.Test; import org.solovyev.android.calculator.model.CalculatorEngine; -import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.view.TextHighlighter; import java.util.Date; diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java index 4247f1b8..af7f103e 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java @@ -1,321 +1,320 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - * or visit http://se.solovyev.org - */ - -package org.solovyev.android.calculator.history; - -import jscl.math.Generic; -import junit.framework.Assert; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.Test; -import org.solovyev.android.calculator.CalculatorDisplay; -import org.solovyev.android.calculator.Editor; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.equals.CollectionEqualizer; -import org.solovyev.common.equals.EqualsTool; -import org.solovyev.common.history.HistoryHelper; -import org.solovyev.common.history.SimpleHistoryHelper; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * User: serso - * Date: 12/17/11 - * Time: 10:01 PM - */ -public class HistoryUtilsTest { - - @Test - public void testFromXml() throws Exception { - - } - - private static final String emptyHistory = "\n" + - " \n" + - ""; - - private static final String toXml1 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 1+1\n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " Error\n" + - " \n" + - " simplify\n" + - " \n" + - " \n" + - " \n" + - ""; - - private static final String toXml2 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 1+1\n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " Error\n" + - " \n" + - " simplify\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 2\n" + - " 5/6\n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 5/6\n" + - " \n" + - " numeric\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " null\n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " Error\n" + - " \n" + - " elementary\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 0\n" + - " 4+5/35sin(41)+dfdsfsdfs\n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " 4+5/35sin(41)+dfdsfsdfs\n" + - " \n" + - " numeric\n" + - " \n" + - " \n" + - " \n" + - ""; - - @Test - public void testToXml() throws Exception { - final Date date = new Date(100000000); - - HistoryHelper history = new SimpleHistoryHelper(); - - CalculatorDisplay calculatorDisplay = new TestCalculatorDisplay(); - calculatorDisplay.setErrorMessage("error_msg1"); - calculatorDisplay.setText("Error"); - calculatorDisplay.setSelection(1); - calculatorDisplay.setJsclOperation(JsclOperation.simplify); - - Editor calculatorEditor = new TestEditor(); - calculatorEditor.setSelection(3); - calculatorEditor.setText("1+1"); - - CalculatorHistoryState state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); - state.setTime(date.getTime()); - history.addState(state); - - Assert.assertEquals(emptyHistory, HistoryUtils.toXml(history.getStates())); - - - state.setSaved(true); - - Assert.assertEquals(toXml1, HistoryUtils.toXml(history.getStates())); - - calculatorDisplay = new TestCalculatorDisplay(); - calculatorDisplay.setErrorMessage(null); - calculatorDisplay.setText("5/6"); - calculatorDisplay.setSelection(3); - calculatorDisplay.setJsclOperation(JsclOperation.numeric); - - calculatorEditor = new TestEditor(); - calculatorEditor.setSelection(2); - calculatorEditor.setText("5/6"); - - state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); - state.setSaved(true); - state.setTime(date.getTime()); - history.addState(state); - - calculatorDisplay = new TestCalculatorDisplay(); - calculatorDisplay.setErrorMessage("error_msg2"); - calculatorDisplay.setText("Error"); - calculatorDisplay.setSelection(1); - calculatorDisplay.setJsclOperation(JsclOperation.elementary); - - calculatorEditor = new TestEditor(); - calculatorEditor.setSelection(1); - calculatorEditor.setText(null); - - state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); - state.setSaved(true); - state.setTime(date.getTime()); - history.addState(state); - - calculatorDisplay = new TestCalculatorDisplay(); - calculatorDisplay.setErrorMessage(null); - calculatorDisplay.setText("4+5/35sin(41)+dfdsfsdfs"); - calculatorDisplay.setSelection(1); - calculatorDisplay.setJsclOperation(JsclOperation.numeric); - - calculatorEditor = new TestEditor(); - calculatorEditor.setSelection(0); - calculatorEditor.setText("4+5/35sin(41)+dfdsfsdfs"); - - state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); - state.setSaved(true); - state.setTime(date.getTime()); - history.addState(state); - - String xml = HistoryUtils.toXml(history.getStates()); - Assert.assertEquals(toXml2, xml); - - final List fromXml = new ArrayList(); - final HistoryHelper historyFromXml = new SimpleHistoryHelper(); - HistoryUtils.fromXml(xml, fromXml); - for (CalculatorHistoryState historyState : fromXml) { - historyFromXml.addState(historyState); - } - - Assert.assertEquals(history.getStates().size(), historyFromXml.getStates().size()); - - for (CalculatorHistoryState historyState : history.getStates()) { - historyState.setId(0); - historyState.setSaved(true); - } - for (CalculatorHistoryState historyState : historyFromXml.getStates()) { - historyState.setId(0); - historyState.setSaved(true); - } - Assert.assertTrue(EqualsTool.areEqual(history.getStates(), historyFromXml.getStates(), new CollectionEqualizer(null))); - } - - - private static class TestCalculatorDisplay implements CalculatorDisplay { - - @NotNull - private final TestEditor testEditor = new TestEditor(); - - private boolean valid; - - private String errorMessage; - - private JsclOperation operation; - - private Generic genericResult; - - @Override - public boolean isValid() { - return this.valid; - } - - @Override - public void setValid(boolean valid) { - this.valid = valid; - } - - @Override - public String getErrorMessage() { - return this.errorMessage; - } - - @Override - public void setErrorMessage(@Nullable String errorMessage) { - this.errorMessage = errorMessage; - } - - @Override - public void setJsclOperation(@NotNull JsclOperation jsclOperation) { - this.operation = jsclOperation; - } - - @NotNull - @Override - public JsclOperation getJsclOperation() { - return this.operation; - } - - @Override - public void setGenericResult(@Nullable Generic genericResult) { - this.genericResult = genericResult; - } - - @Override - public Generic getGenericResult() { - return this.genericResult; - } - - @Override - public CharSequence getText() { - return this.testEditor.getText(); - } - - @Override - public void setText(@Nullable CharSequence text) { - this.testEditor.setText(text); - } - - @Override - public int getSelection() { - return this.testEditor.getSelection(); - } - - @Override - public void setSelection(int selection) { - this.testEditor.setSelection(selection); - } - } - - private static class TestEditor implements Editor { - - @Nullable - private CharSequence text; - - private int selection; - - @Nullable - @Override - public CharSequence getText() { - return this.text; - } - - @Override - public void setText(@Nullable CharSequence text) { - this.text = text; - } - - @Override - public int getSelection() { - return this.selection; - } - - @Override - public void setSelection(int selection) { - this.selection = selection; - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + * or visit http://se.solovyev.org + */ + +package org.solovyev.android.calculator.history; + +import jscl.math.Generic; +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.solovyev.android.calculator.ICalculatorDisplay; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.common.equals.CollectionEqualizer; +import org.solovyev.common.equals.EqualsTool; +import org.solovyev.common.history.HistoryHelper; +import org.solovyev.common.history.SimpleHistoryHelper; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * User: serso + * Date: 12/17/11 + * Time: 10:01 PM + */ +public class HistoryUtilsTest { + + @Test + public void testFromXml() throws Exception { + + } + + private static final String emptyHistory = "\n" + + " \n" + + ""; + + private static final String toXml1 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 1+1\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " Error\n" + + " \n" + + " simplify\n" + + " \n" + + " \n" + + " \n" + + ""; + + private static final String toXml2 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 1+1\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " Error\n" + + " \n" + + " simplify\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 2\n" + + " 5/6\n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 5/6\n" + + " \n" + + " numeric\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " null\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " Error\n" + + " \n" + + " elementary\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " 4+5/35sin(41)+dfdsfsdfs\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 4+5/35sin(41)+dfdsfsdfs\n" + + " \n" + + " numeric\n" + + " \n" + + " \n" + + " \n" + + ""; + + @Test + public void testToXml() throws Exception { + final Date date = new Date(100000000); + + HistoryHelper history = new SimpleHistoryHelper(); + + ICalculatorDisplay calculatorDisplay = new TestCalculatorDisplay(); + calculatorDisplay.setErrorMessage("error_msg1"); + calculatorDisplay.setText("Error"); + calculatorDisplay.setSelection(1); + calculatorDisplay.setJsclOperation(JsclOperation.simplify); + + Editor calculatorEditor = new TestEditor(); + calculatorEditor.setSelection(3); + calculatorEditor.setText("1+1"); + + CalculatorHistoryState state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); + state.setTime(date.getTime()); + history.addState(state); + + Assert.assertEquals(emptyHistory, HistoryUtils.toXml(history.getStates())); + + + state.setSaved(true); + + Assert.assertEquals(toXml1, HistoryUtils.toXml(history.getStates())); + + calculatorDisplay = new TestCalculatorDisplay(); + calculatorDisplay.setErrorMessage(null); + calculatorDisplay.setText("5/6"); + calculatorDisplay.setSelection(3); + calculatorDisplay.setJsclOperation(JsclOperation.numeric); + + calculatorEditor = new TestEditor(); + calculatorEditor.setSelection(2); + calculatorEditor.setText("5/6"); + + state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); + state.setSaved(true); + state.setTime(date.getTime()); + history.addState(state); + + calculatorDisplay = new TestCalculatorDisplay(); + calculatorDisplay.setErrorMessage("error_msg2"); + calculatorDisplay.setText("Error"); + calculatorDisplay.setSelection(1); + calculatorDisplay.setJsclOperation(JsclOperation.elementary); + + calculatorEditor = new TestEditor(); + calculatorEditor.setSelection(1); + calculatorEditor.setText(null); + + state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); + state.setSaved(true); + state.setTime(date.getTime()); + history.addState(state); + + calculatorDisplay = new TestCalculatorDisplay(); + calculatorDisplay.setErrorMessage(null); + calculatorDisplay.setText("4+5/35sin(41)+dfdsfsdfs"); + calculatorDisplay.setSelection(1); + calculatorDisplay.setJsclOperation(JsclOperation.numeric); + + calculatorEditor = new TestEditor(); + calculatorEditor.setSelection(0); + calculatorEditor.setText("4+5/35sin(41)+dfdsfsdfs"); + + state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); + state.setSaved(true); + state.setTime(date.getTime()); + history.addState(state); + + String xml = HistoryUtils.toXml(history.getStates()); + Assert.assertEquals(toXml2, xml); + + final List fromXml = new ArrayList(); + final HistoryHelper historyFromXml = new SimpleHistoryHelper(); + HistoryUtils.fromXml(xml, fromXml); + for (CalculatorHistoryState historyState : fromXml) { + historyFromXml.addState(historyState); + } + + Assert.assertEquals(history.getStates().size(), historyFromXml.getStates().size()); + + for (CalculatorHistoryState historyState : history.getStates()) { + historyState.setId(0); + historyState.setSaved(true); + } + for (CalculatorHistoryState historyState : historyFromXml.getStates()) { + historyState.setId(0); + historyState.setSaved(true); + } + Assert.assertTrue(EqualsTool.areEqual(history.getStates(), historyFromXml.getStates(), new CollectionEqualizer(null))); + } + + + private static class TestCalculatorDisplay implements ICalculatorDisplay { + + @NotNull + private final TestEditor testEditor = new TestEditor(); + + private boolean valid; + + private String errorMessage; + + private JsclOperation operation; + + private Generic genericResult; + + @Override + public boolean isValid() { + return this.valid; + } + + @Override + public void setValid(boolean valid) { + this.valid = valid; + } + + @Override + public String getErrorMessage() { + return this.errorMessage; + } + + @Override + public void setErrorMessage(@Nullable String errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public void setJsclOperation(@NotNull JsclOperation jsclOperation) { + this.operation = jsclOperation; + } + + @NotNull + @Override + public JsclOperation getJsclOperation() { + return this.operation; + } + + @Override + public void setGenericResult(@Nullable Generic genericResult) { + this.genericResult = genericResult; + } + + @Override + public Generic getGenericResult() { + return this.genericResult; + } + + @Override + public CharSequence getText() { + return this.testEditor.getText(); + } + + @Override + public void setText(@Nullable CharSequence text) { + this.testEditor.setText(text); + } + + @Override + public int getSelection() { + return this.testEditor.getSelection(); + } + + @Override + public void setSelection(int selection) { + this.testEditor.setSelection(selection); + } + } + + private static class TestEditor implements Editor { + + @Nullable + private CharSequence text; + + private int selection; + + @Nullable + @Override + public CharSequence getText() { + return this.text; + } + + @Override + public void setText(@Nullable CharSequence text) { + this.text = text; + } + + @Override + public int getSelection() { + return this.selection; + } + + @Override + public void setSelection(int selection) { + this.selection = selection; + } + } +} diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java index 375969ef..ac83a8bd 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java @@ -1,445 +1,443 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator.model; - -import jscl.AngleUnit; -import jscl.JsclMathEngine; -import jscl.NumeralBase; -import jscl.math.Expression; -import jscl.math.Generic; -import jscl.math.function.Constant; -import jscl.math.function.CustomFunction; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.solovyev.android.calculator.CalculatorEvalException; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.jscl.JsclOperation; - -import java.text.DecimalFormatSymbols; -import java.util.Locale; - -import static junit.framework.Assert.fail; - -/** - * User: serso - * Date: 9/17/11 - * Time: 9:47 PM - */ - -public class CalculatorEngineTest { - - @BeforeClass - public static void setUp() throws Exception { - CalculatorEngine.instance.init(null, null); - CalculatorEngine.instance.setPrecision(3); - CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); - } - - @Test - public void testDegrees() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); - try { - cm.getEngine().setAngleUnits(AngleUnit.rad); - cm.setPrecision(3); - try { - Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "°")); - fail(); - } catch (CalculatorParseException e) { - - } - - Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "1°").getStringResult()); - Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getStringResult()); - Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getStringResult()); - Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getStringResult()); - Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getStringResult()); - - Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getStringResult()); - } finally { - cm.getEngine().setAngleUnits(defaultAngleUnit); - } - } - - @Test - public void testLongExecution() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - try { - cm.evaluate(JsclOperation.numeric, "3^10^10^10"); - Assert.fail(); - } catch (CalculatorParseException e) { - if (e.getMessageCode().equals(Messages.msg_3)) { - - } else { - System.out.print(e.getCause().getMessage()); - Assert.fail(); - } - } - - try { - cm.evaluate(JsclOperation.numeric, "9999999!"); - Assert.fail(); - } catch (CalculatorParseException e) { - if (e.getMessageCode().equals(Messages.msg_3)) { - - } else { - System.out.print(e.getCause().getMessage()); - Assert.fail(); - } - } - - /*final long start = System.currentTimeMillis(); - try { - cm.evaluate(JsclOperation.numeric, "3^10^10^10"); - Assert.fail(); - } catch (ParseException e) { - if (e.getMessage().startsWith("Too long calculation")) { - final long end = System.currentTimeMillis(); - Assert.assertTrue(end - start < 1000); - } else { - Assert.fail(); - } - }*/ - - } - - @Test - public void testEvaluate() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getStringResult()); - - final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%"); - expression.substitute(new Constant("t"), Expression.valueOf(100d)); - - Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getStringResult()); - Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getStringResult()); - Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getStringResult()); - final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); - try { - cm.getEngine().setAngleUnits(AngleUnit.rad); - Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getStringResult()); - Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getStringResult()); - Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getStringResult()); - Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getStringResult()); - Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getStringResult()); - } finally { - cm.getEngine().setAngleUnits(defaultAngleUnit); - } - Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getStringResult()); - Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getStringResult()); - Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getStringResult()); - Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getStringResult()); - try { - cm.getEngine().setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getStringResult()); - Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getStringResult()); - } finally { - cm.getEngine().setAngleUnits(defaultAngleUnit); - } - Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getStringResult()); - Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getStringResult()); - Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getStringResult()); - Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getStringResult()); - Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getStringResult()); - Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getStringResult()); - Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getStringResult()); - Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getStringResult()); - - junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getStringResult()); - junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getStringResult()); - junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getStringResult()); - junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getStringResult()); - junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getStringResult()); - junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getStringResult()); - junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString()); - junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString()); - try { - junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getStringResult()); - fail(); - } catch (CalculatorParseException e) { - } - - junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getStringResult()); - - try { - junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getStringResult()); - fail(); - } catch (CalculatorParseException e) { - - } - junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getStringResult()); - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d)); - - try { - cm.getEngine().setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getStringResult()); - Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getStringResult()); - Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getStringResult()); - Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getStringResult()); - Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getStringResult()); - Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getStringResult()); - } finally { - cm.getEngine().setAngleUnits(defaultAngleUnit); - } - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d)); - Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getStringResult()); - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d)); - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d)); - Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getStringResult()); - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null)); - Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getStringResult()); - Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getStringResult()); - Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "∞").getStringResult()); - Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "Infinity").getStringResult()); - Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getStringResult()); - Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getStringResult()); - - Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getStringResult()); - Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getStringResult()); - - Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getStringResult()); - - try { - cm.getEngine().setNumeralBase(NumeralBase.hex); - Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getStringResult()); - Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getStringResult()); - Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getStringResult()); - Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getStringResult()); - } finally { - cm.getEngine().setNumeralBase(NumeralBase.dec); - } - - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getStringResult()); - - - /* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult()); - Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult()); - Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult()); - try { - Assert.assertEquals("0.278", cm.evaluate(JsclOperation.numeric, "30°^2").getResult()); - junit.framework.Assert.fail(); - } catch (ParseException e) { - if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) { - junit.framework.Assert.fail(); - } - }*/ - -/* try { - cm.setTimeout(5000); - Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult()); - } finally { - cm.setTimeout(3000); - }*/ - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null)); - Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult()); - Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getStringResult()); - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2")); - Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult()); - Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getStringResult()); - - Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)")); - Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)")); - - Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(ln(10)/ln(x), x)")); - Assert.assertEquals("∫(ln(10)/ln(x), x)", Expression.valueOf("∫(log(x, 10), x)").expand().toString()); - Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(log(x, 10), x)")); - } - - @Test - public void testFormatting() throws Exception { - final CalculatorEngine ce = CalculatorEngine.instance; - - Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getStringResult()); - - } - - @Test - public void testI() throws CalculatorParseException, CalculatorEvalException { - final CalculatorEngine cm = CalculatorEngine.instance; - - Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getStringResult()); - for (int i = 0; i < 1000; i++) { - double real = (Math.random()-0.5) * 1000; - double imag = (Math.random()-0.5) * 1000; - int exp = (int)(Math.random() * 10); - - final StringBuilder sb = new StringBuilder(); - sb.append(real); - if ( imag > 0 ) { - sb.append("+"); - } - sb.append(imag); - sb.append("^").append(exp); - try { - cm.evaluate(JsclOperation.numeric, sb.toString()).getStringResult(); - } catch (Throwable e) { - fail(sb.toString()); - } - } - } - - @Test - public void testEmptyFunction() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - try { - cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))"); - Assert.fail(); - } catch (CalculatorParseException e) { - } - Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getStringResult()); - try { - cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))"); - Assert.fail(); - } catch (CalculatorParseException e) { - } - - final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); - try { - cm.getEngine().setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getStringResult()); - } finally { - cm.getEngine().setAngleUnits(defaultAngleUnit); - } - - CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d)); - Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getStringResult()); - - try { - cm.evaluate(JsclOperation.numeric, "sin"); - Assert.fail(); - } catch (CalculatorParseException e) { - } - } - - @Test - public void testRounding() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - try { - DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); - decimalGroupSymbols.setDecimalSeparator('.'); - decimalGroupSymbols.setGroupingSeparator('\''); - cm.setDecimalGroupSymbols(decimalGroupSymbols); - cm.setPrecision(2); - Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getStringResult()); - cm.setPrecision(10); - Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getStringResult()); - Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getStringResult()); - Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getStringResult()); - } finally { - cm.setPrecision(3); - DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); - decimalGroupSymbols.setDecimalSeparator('.'); - decimalGroupSymbols.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT.charAt(0)); - cm.setDecimalGroupSymbols(decimalGroupSymbols); - } - } - - @Test - public void testComparisonFunction() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getStringResult()); - - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getStringResult()); - - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getStringResult()); - - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getStringResult()); - - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getStringResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getStringResult()); - - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getStringResult()); - - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getStringResult()); - Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getStringResult()); - //Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult()); - Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getStringResult()); - - } - - - @Test - public void testNumeralSystems() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getStringResult()); - Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getStringResult()); - Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getStringResult()); - Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getStringResult()); - Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getStringResult()); - Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getStringResult()); - Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getStringResult()); - Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getStringResult()); - - try { - cm.evaluate(JsclOperation.numeric, "0b:π").getStringResult(); - Assert.fail(); - } catch (CalculatorParseException e) { - // ok - } - - final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase(); - try{ - cm.getEngine().setNumeralBase(NumeralBase.bin); - Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getStringResult()); - Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getStringResult()); - - cm.getEngine().setNumeralBase(NumeralBase.hex); - Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getStringResult()); - Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getStringResult()); - } finally { - cm.setNumeralBase(defaultNumeralBase); - } - } - - @Test - public void testLog() throws Exception { - final CalculatorEngine cm = CalculatorEngine.instance; - - Assert.assertEquals("∞", Expression.valueOf("1/0").numeric().toString()); - Assert.assertEquals("∞", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); - - // logarithm - Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent()); - Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getStringResult()); - Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getStringResult()); - Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getStringResult()); - Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getStringResult()); - Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getStringResult()); - Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getStringResult()); - - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator.model; + +import jscl.AngleUnit; +import jscl.JsclMathEngine; +import jscl.NumeralBase; +import jscl.math.Expression; +import jscl.math.Generic; +import jscl.math.function.Constant; +import jscl.math.function.CustomFunction; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.solovyev.android.calculator.jscl.JsclOperation; + +import java.text.DecimalFormatSymbols; +import java.util.Locale; + +import static junit.framework.Assert.fail; + +/** + * User: serso + * Date: 9/17/11 + * Time: 9:47 PM + */ + +public class CalculatorEngineTest { + + @BeforeClass + public static void setUp() throws Exception { + CalculatorEngine.instance.init(null, null); + CalculatorEngine.instance.setPrecision(3); + CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); + } + + @Test + public void testDegrees() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); + try { + cm.getEngine().setAngleUnits(AngleUnit.rad); + cm.setPrecision(3); + try { + Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "°")); + fail(); + } catch (CalculatorParseException e) { + + } + + Assert.assertEquals("0.017", cm.evaluate(JsclOperation.numeric, "1°").getResult()); + Assert.assertEquals("0.349", cm.evaluate(JsclOperation.numeric, "20.0°").getResult()); + Assert.assertEquals("0.5", cm.evaluate(JsclOperation.numeric, "sin(30°)").getResult()); + Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(sin(30°))").getResult()); + Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.numeric, "∂(cos(t),t,t,1°)").getResult()); + + Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate(JsclOperation.simplify, "∂(cos(t),t,t,1°)").getResult()); + } finally { + cm.getEngine().setAngleUnits(defaultAngleUnit); + } + } + + @Test + public void testLongExecution() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + try { + cm.evaluate(JsclOperation.numeric, "3^10^10^10"); + Assert.fail(); + } catch (CalculatorParseException e) { + if (e.getMessageCode().equals(Messages.msg_3)) { + + } else { + System.out.print(e.getCause().getMessage()); + Assert.fail(); + } + } + + try { + cm.evaluate(JsclOperation.numeric, "9999999!"); + Assert.fail(); + } catch (CalculatorParseException e) { + if (e.getMessageCode().equals(Messages.msg_3)) { + + } else { + System.out.print(e.getCause().getMessage()); + Assert.fail(); + } + } + + /*final long start = System.currentTimeMillis(); + try { + cm.evaluate(JsclOperation.numeric, "3^10^10^10"); + Assert.fail(); + } catch (ParseException e) { + if (e.getMessage().startsWith("Too long calculation")) { + final long end = System.currentTimeMillis(); + Assert.assertTrue(end - start < 1000); + } else { + Assert.fail(); + } + }*/ + + } + + @Test + public void testEvaluate() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + Assert.assertEquals("cos(t)+10%", cm.evaluate(JsclOperation.simplify, "cos(t)+10%").getResult()); + + final Generic expression = cm.getEngine().simplifyGeneric("cos(t)+10%"); + expression.substitute(new Constant("t"), Expression.valueOf(100d)); + + Assert.assertEquals("it", cm.evaluate(JsclOperation.simplify, "it").getResult()); + Assert.assertEquals("10%", cm.evaluate(JsclOperation.simplify, "10%").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq( 1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.simplify, "eq( 1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lg(10)").getResult()); + Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2").getResult()); + final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); + try { + cm.getEngine().setAngleUnits(AngleUnit.rad); + Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)").getResult()); + Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)").getResult()); + Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)").getResult()); + Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult()); + Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)").getResult()); + } finally { + cm.getEngine().setAngleUnits(defaultAngleUnit); + } + Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2").getResult()); + Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2").getResult()); + Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)").getResult()); + Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+√(-1)").getResult()); + try { + cm.getEngine().setAngleUnits(AngleUnit.rad); + Assert.assertEquals("0.921+Πi", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))").getResult()); + Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)").getResult()); + } finally { + cm.getEngine().setAngleUnits(defaultAngleUnit); + } + Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)").getResult()); + Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)").getResult()); + Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)").getResult()); + Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i").getResult()); + Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i").getResult()); + Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getResult()); + Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getResult()); + Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getResult()); + + junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getResult()); + junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getResult()); + junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getResult()); + junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult()); + junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult()); + junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "(3!)!").getResult()); + junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString()); + junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString()); + try { + junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult()); + fail(); + } catch (CalculatorParseException e) { + } + + junit.framework.Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "(π/π)!").getResult()); + + try { + junit.framework.Assert.assertEquals("i", cm.evaluate(JsclOperation.numeric, "(-1)i!").getResult()); + fail(); + } catch (CalculatorParseException e) { + + } + junit.framework.Assert.assertEquals("24i", cm.evaluate(JsclOperation.numeric, "4!i").getResult()); + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d)); + + try { + cm.getEngine().setAngleUnits(AngleUnit.rad); + Assert.assertEquals("0.451", cm.evaluate(JsclOperation.numeric, "acos(0.8999999999999811)").getResult()); + Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)").getResult()); + Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si").getResult()); + Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si").getResult()); + Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si").getResult()); + Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si").getResult()); + } finally { + cm.getEngine().setAngleUnits(defaultAngleUnit); + } + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("s", 1d)); + Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult()); + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k", 3.5d)); + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("k1", 4d)); + Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11").getResult()); + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null)); + Assert.assertEquals("11t", cm.evaluate(JsclOperation.numeric, "t11").getResult()); + Assert.assertEquals("11et", cm.evaluate(JsclOperation.numeric, "t11e").getResult()); + Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "∞").getResult()); + Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "Infinity").getResult()); + Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getResult()); + Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getResult()); + + Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getResult()); + Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getResult()); + + Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult()); + + try { + cm.getEngine().setNumeralBase(NumeralBase.hex); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getResult()); + } finally { + cm.getEngine().setNumeralBase(NumeralBase.dec); + } + + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getResult()); + + + /* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult()); + Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult()); + Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult()); + try { + Assert.assertEquals("0.278", cm.evaluate(JsclOperation.numeric, "30°^2").getResult()); + junit.framework.Assert.fail(); + } catch (ParseException e) { + if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) { + junit.framework.Assert.fail(); + } + }*/ + +/* try { + cm.setTimeout(5000); + Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult()); + } finally { + cm.setTimeout(3000); + }*/ + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", (String) null)); + Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult()); + Assert.assertEquals("2t", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult()); + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("t", "2")); + Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getResult()); + Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "∂(t^2,t)").getResult()); + + Assert.assertEquals("-x+x*ln(x)", cm.getEngine().simplify("∫(ln(x), x)")); + Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.getEngine().simplify("∫(log(10, x), x)")); + + Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(ln(10)/ln(x), x)")); + Assert.assertEquals("∫(ln(10)/ln(x), x)", Expression.valueOf("∫(log(x, 10), x)").expand().toString()); + Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.getEngine().simplify("∫(log(x, 10), x)")); + } + + @Test + public void testFormatting() throws Exception { + final CalculatorEngine ce = CalculatorEngine.instance; + + Assert.assertEquals("12 345", ce.evaluate(JsclOperation.simplify, "12345").getResult()); + + } + + @Test + public void testI() throws CalculatorParseException, CalculatorEvalException { + final CalculatorEngine cm = CalculatorEngine.instance; + + Assert.assertEquals("-i", cm.evaluate(JsclOperation.numeric, "i^3").getResult()); + for (int i = 0; i < 1000; i++) { + double real = (Math.random()-0.5) * 1000; + double imag = (Math.random()-0.5) * 1000; + int exp = (int)(Math.random() * 10); + + final StringBuilder sb = new StringBuilder(); + sb.append(real); + if ( imag > 0 ) { + sb.append("+"); + } + sb.append(imag); + sb.append("^").append(exp); + try { + cm.evaluate(JsclOperation.numeric, sb.toString()).getResult(); + } catch (Throwable e) { + fail(sb.toString()); + } + } + } + + @Test + public void testEmptyFunction() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + try { + cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))"); + Assert.fail(); + } catch (CalculatorParseException e) { + } + Assert.assertEquals("0.34+1.382i", cm.evaluate(JsclOperation.numeric, "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))").getResult()); + try { + cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos())))))))))))))))))))))))))))))))))))"); + Assert.fail(); + } catch (CalculatorParseException e) { + } + + final AngleUnit defaultAngleUnit = cm.getEngine().getAngleUnits(); + try { + cm.getEngine().setAngleUnits(AngleUnit.rad); + Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))").getResult()); + } finally { + cm.getEngine().setAngleUnits(defaultAngleUnit); + } + + CalculatorEngine.instance.getVarsRegistry().add(new Var.Builder("si", 5d)); + Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si").getResult()); + + try { + cm.evaluate(JsclOperation.numeric, "sin"); + Assert.fail(); + } catch (CalculatorParseException e) { + } + } + + @Test + public void testRounding() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + try { + DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); + decimalGroupSymbols.setDecimalSeparator('.'); + decimalGroupSymbols.setGroupingSeparator('\''); + cm.setDecimalGroupSymbols(decimalGroupSymbols); + cm.setPrecision(2); + Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); + cm.setPrecision(10); + Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); + Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult()); + Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getResult()); + } finally { + cm.setPrecision(3); + DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); + decimalGroupSymbols.setDecimalSeparator('.'); + decimalGroupSymbols.setGroupingSeparator(JsclMathEngine.GROUPING_SEPARATOR_DEFAULT.charAt(0)); + cm.setDecimalGroupSymbols(decimalGroupSymbols); + } + } + + @Test + public void testComparisonFunction() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(0, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "eq(1, 1.0)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 1.000000000000001)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "eq(1, 0)").getResult()); + + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "lt(0, 1)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 1)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "lt(1, 0)").getResult()); + + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(0, 1)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "gt(1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "gt(1, 0)").getResult()); + + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(0, 1)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ne(1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ne(1, 0)").getResult()); + + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(0, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "le(1, 1)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "le(1, 0)").getResult()); + + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ge(0, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ge(1, 0)").getResult()); + + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(0, 1)").getResult()); + Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1)").getResult()); + //Assert.assertEquals("1", cm.evaluate(JsclOperation.numeric, "ap(1, 1.000000000000001)").getResult()); + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "ap(1, 0)").getResult()); + + } + + + @Test + public void testNumeralSystems() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + Assert.assertEquals("11 259 375", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF").getResult()); + Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e").getResult()); + Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF").getResult()); + Assert.assertEquals("e", cm.evaluate(JsclOperation.numeric, "e*0x:ABCDEF/0x:ABCDEF").getResult()); + Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF").getResult()); + Assert.assertEquals("30 606 154.462", cm.evaluate(JsclOperation.numeric, "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C").getResult()); + Assert.assertEquals("1 446 257 064 651.832", cm.evaluate(JsclOperation.numeric, "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ").getResult()); + Assert.assertEquals("13", cm.evaluate(JsclOperation.numeric, "0b:1101").getResult()); + + try { + cm.evaluate(JsclOperation.numeric, "0b:π").getResult(); + Assert.fail(); + } catch (CalculatorParseException e) { + // ok + } + + final NumeralBase defaultNumeralBase = cm.getEngine().getNumeralBase(); + try{ + cm.getEngine().setNumeralBase(NumeralBase.bin); + Assert.assertEquals("101", cm.evaluate(JsclOperation.numeric, "10+11").getResult()); + Assert.assertEquals("10/11", cm.evaluate(JsclOperation.numeric, "10/11").getResult()); + + cm.getEngine().setNumeralBase(NumeralBase.hex); + Assert.assertEquals("63 7B", cm.evaluate(JsclOperation.numeric, "56CE+CAD").getResult()); + Assert.assertEquals("E", cm.evaluate(JsclOperation.numeric, "E").getResult()); + } finally { + cm.setNumeralBase(defaultNumeralBase); + } + } + + @Test + public void testLog() throws Exception { + final CalculatorEngine cm = CalculatorEngine.instance; + + Assert.assertEquals("∞", Expression.valueOf("1/0").numeric().toString()); + Assert.assertEquals("∞", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); + + // logarithm + Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent()); + Assert.assertEquals("∞", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getResult()); + Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getResult()); + Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getResult()); + Assert.assertEquals("0.96", cm.evaluate(JsclOperation.numeric, "log(11, 10)").getResult()); + Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getResult()); + Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getResult()); + + } +} diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessorTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessorTest.java index a52ee3af..dd89677b 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessorTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessorTest.java @@ -3,7 +3,6 @@ package org.solovyev.android.calculator.model; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor; import java.text.DecimalFormatSymbols; diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/NumeralBaseTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/NumeralBaseTest.java index 5e05495c..94989a3a 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/NumeralBaseTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/NumeralBaseTest.java @@ -1,148 +1,146 @@ -package org.solovyev.android.calculator.model; - -import au.com.bytecode.opencsv.CSVReader; -import jscl.JsclMathEngine; -import jscl.MathEngine; -import jscl.math.Expression; -import jscl.text.ParseException; -import jscl.util.ExpressionGeneratorWithInput; -import org.jetbrains.annotations.NotNull; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.solovyev.android.calculator.CalculatorEvalException; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.common.Converter; - -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -/** - * User: serso - * Date: 12/14/11 - * Time: 4:16 PM - */ -public class NumeralBaseTest { - - @BeforeClass - public static void setUp() throws Exception { - CalculatorEngine.instance.init(null, null); - CalculatorEngine.instance.setPrecision(3); - CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); - } - - @Test - public void testConversion() throws Exception { - CSVReader reader = null; - try { - final MathEngine me = JsclMathEngine.instance; - - reader = new CSVReader(new InputStreamReader(NumeralBaseTest.class.getResourceAsStream("/org/solovyev/android/calculator/model/nb_table.csv")), '\t'); - - // skip first line - reader.readNext(); - - String[] line = reader.readNext(); - for (; line != null; line = reader.readNext()) { - testExpression(line, new DummyExpression()); - testExpression(line, new Expression1()); - testExpression(line, new Expression2()); - testExpression(line, new Expression3()); - - final String dec = line[0].toUpperCase(); - final String hex = "0x:" + line[1].toUpperCase(); - final String bin = "0b:" + line[2].toUpperCase(); - - final List input = new ArrayList(); - input.add(dec); - input.add(hex); - input.add(bin); - - //System.out.println("Dec: " + dec); - //System.out.println("Hex: " + hex); - //System.out.println("Bin: " + bin); - - final ExpressionGeneratorWithInput eg = new ExpressionGeneratorWithInput(input, 20); - final List expressions = eg.generate(); - - final String decExpression = expressions.get(0); - final String hexExpression = expressions.get(1); - final String binExpression = expressions.get(2); - - //System.out.println("Dec expression: " + decExpression); - //System.out.println("Hex expression: " + hexExpression); - //System.out.println("Bin expression: " + binExpression); - - final String decResult = Expression.valueOf(decExpression).numeric().toString(); - //System.out.println("Dec result: " + decResult); - - final String hexResult = Expression.valueOf(hexExpression).numeric().toString(); - //System.out.println("Hex result: " + hexResult); - - final String binResult = Expression.valueOf(binExpression).numeric().toString(); - //System.out.println("Bin result: " + binResult); - - Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult); - Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); - } - } finally { - if (reader != null) { - reader.close(); - } - } - } - - public static void testExpression(@NotNull String[] line, @NotNull Converter converter) throws ParseException, CalculatorEvalException, CalculatorParseException { - final String dec = line[0].toUpperCase(); - final String hex = "0x:" + line[1].toUpperCase(); - final String bin = "0b:" + line[2].toUpperCase(); - - final String decExpression = converter.convert(dec); - final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getStringResult(); - final String hexExpression = converter.convert(hex); - final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getStringResult(); - final String binExpression = converter.convert(bin); - final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getStringResult(); - - Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult); - Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); - } - - private static class DummyExpression implements Converter { - - @NotNull - @Override - public String convert(@NotNull String s) { - return s; - } - } - - private static class Expression1 implements Converter { - - @NotNull - @Override - public String convert(@NotNull String s) { - return s + "*" + s; - } - } - - private static class Expression2 implements Converter { - - @NotNull - @Override - public String convert(@NotNull String s) { - return s + "*" + s + " * sin(" + s + ") - 0b:1101"; - } - } - - private static class Expression3 implements Converter { - - @NotNull - @Override - public String convert(@NotNull String s) { - return s + "*" + s + " * sin(" + s + ") - 0b:1101 + √(" + s + ") + exp ( " + s + ")"; - } - } -} +package org.solovyev.android.calculator.model; + +import au.com.bytecode.opencsv.CSVReader; +import jscl.JsclMathEngine; +import jscl.MathEngine; +import jscl.math.Expression; +import jscl.text.ParseException; +import jscl.util.ExpressionGeneratorWithInput; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.common.Converter; + +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * User: serso + * Date: 12/14/11 + * Time: 4:16 PM + */ +public class NumeralBaseTest { + + @BeforeClass + public static void setUp() throws Exception { + CalculatorEngine.instance.init(null, null); + CalculatorEngine.instance.setPrecision(3); + CalculatorEngine.instance.setThreadKiller(new CalculatorEngine.ThreadKillerImpl()); + } + + @Test + public void testConversion() throws Exception { + CSVReader reader = null; + try { + final MathEngine me = JsclMathEngine.instance; + + reader = new CSVReader(new InputStreamReader(NumeralBaseTest.class.getResourceAsStream("/org/solovyev/android/calculator/model/nb_table.csv")), '\t'); + + // skip first line + reader.readNext(); + + String[] line = reader.readNext(); + for (; line != null; line = reader.readNext()) { + testExpression(line, new DummyExpression()); + testExpression(line, new Expression1()); + testExpression(line, new Expression2()); + testExpression(line, new Expression3()); + + final String dec = line[0].toUpperCase(); + final String hex = "0x:" + line[1].toUpperCase(); + final String bin = "0b:" + line[2].toUpperCase(); + + final List input = new ArrayList(); + input.add(dec); + input.add(hex); + input.add(bin); + + //System.out.println("Dec: " + dec); + //System.out.println("Hex: " + hex); + //System.out.println("Bin: " + bin); + + final ExpressionGeneratorWithInput eg = new ExpressionGeneratorWithInput(input, 20); + final List expressions = eg.generate(); + + final String decExpression = expressions.get(0); + final String hexExpression = expressions.get(1); + final String binExpression = expressions.get(2); + + //System.out.println("Dec expression: " + decExpression); + //System.out.println("Hex expression: " + hexExpression); + //System.out.println("Bin expression: " + binExpression); + + final String decResult = Expression.valueOf(decExpression).numeric().toString(); + //System.out.println("Dec result: " + decResult); + + final String hexResult = Expression.valueOf(hexExpression).numeric().toString(); + //System.out.println("Hex result: " + hexResult); + + final String binResult = Expression.valueOf(binExpression).numeric().toString(); + //System.out.println("Bin result: " + binResult); + + Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult); + Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); + } + } finally { + if (reader != null) { + reader.close(); + } + } + } + + public static void testExpression(@NotNull String[] line, @NotNull Converter converter) throws ParseException, CalculatorEvalException, CalculatorParseException { + final String dec = line[0].toUpperCase(); + final String hex = "0x:" + line[1].toUpperCase(); + final String bin = "0b:" + line[2].toUpperCase(); + + final String decExpression = converter.convert(dec); + final String decResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, decExpression).getResult(); + final String hexExpression = converter.convert(hex); + final String hexResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, hexExpression).getResult(); + final String binExpression = converter.convert(bin); + final String binResult = CalculatorEngine.instance.evaluate(JsclOperation.numeric, binExpression).getResult(); + + Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult); + Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult); + } + + private static class DummyExpression implements Converter { + + @NotNull + @Override + public String convert(@NotNull String s) { + return s; + } + } + + private static class Expression1 implements Converter { + + @NotNull + @Override + public String convert(@NotNull String s) { + return s + "*" + s; + } + } + + private static class Expression2 implements Converter { + + @NotNull + @Override + public String convert(@NotNull String s) { + return s + "*" + s + " * sin(" + s + ") - 0b:1101"; + } + } + + private static class Expression3 implements Converter { + + @NotNull + @Override + public String convert(@NotNull String s) { + return s + "*" + s + " * sin(" + s + ") - 0b:1101 + √(" + s + ") + exp ( " + s + ")"; + } + } +} diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java index 05c4e995..c4372638 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java @@ -11,10 +11,6 @@ import jscl.NumeralBase; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.solovyev.android.calculator.CalculatorParseException; -import org.solovyev.android.calculator.PreparedExpression; -import org.solovyev.android.calculator.ToJsclTextProcessor; -import org.solovyev.android.calculator.text.TextProcessor; /** * User: serso diff --git a/pom.xml b/pom.xml index 61bbd3f4..a4352372 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,6 @@ calculatorpp calculatorpp-service calculatorpp-test - calculatorpp-core @@ -72,18 +71,6 @@ 1.0.0 - - org.solovyev - jscl - 0.0.2 - - - xercesImpl - xerces - - - - org.solovyev.android android-common-other @@ -94,13 +81,7 @@ junit junit - 4.8.2 - - - - com.intellij - annotations - 7.0.3 + 4.8.1 @@ -122,22 +103,6 @@ 11.0.2 - - org.simpleframework - simple-xml - 2.6.1 - - - stax-api - stax - - - xpp3 - xpp3 - - - - From fcb835724edaf77855f321a1415a99c53b8ac180 Mon Sep 17 00:00:00 2001 From: serso Date: Thu, 11 Oct 2012 12:44:25 +0400 Subject: [PATCH 3/3] project.properties --- calculatorpp/project.properties | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/calculatorpp/project.properties b/calculatorpp/project.properties index 0b0ebc4d..03180409 100644 --- a/calculatorpp/project.properties +++ b/calculatorpp/project.properties @@ -9,12 +9,16 @@ # Project target. target=android-15 -android.library.reference.1=../calculatorpp-service -android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 -android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 -android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 -android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 -android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 -android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 +android.library.reference.1=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 +android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 +android.library.reference.3=gen-external-apklibs/org.solovyev.android_billing_0.2 +android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-db_1.0.0 +android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 +android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 +android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 +android.library.reference.8=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 +android.library.reference.9=gen-external-apklibs/org.solovyev.android_android-common-sherlock_1.0.0 +android.library.reference.10=gen-external-apklibs/com.actionbarsherlock_library_4.1.0 +android.library.reference.11=gen-external-apklibs/org.solovyev.android_android-common-list_1.0.0