From 21640c051a7c9d1fd35aea31bddb762e693ebe04 Mon Sep 17 00:00:00 2001 From: serso Date: Tue, 9 Oct 2012 17:21:58 +0400 Subject: [PATCH] tests + proguard --- .../calculator/CalculatorEventType.java | 259 +++-- .../android/calculator/CalculatorImpl.java | 944 +++++++++--------- .../calculator/CalculatorLocatorImpl.java | 226 ++--- .../android/calculator/history/History.java | 2 +- .../calculator/CalculatorTestUtils.java | 171 +++- .../model/AndroidCalculatorEngineTest.java | 874 ++++++++-------- calculatorpp/proguard.cfg | 161 +-- .../model/AndroidMathEntityDao.java | 194 ++-- pom.xml | 553 +++++----- 9 files changed, 1758 insertions(+), 1626 deletions(-) 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 ec8af566..6bb96dd0 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,132 +1,127 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:40 - */ -public enum CalculatorEventType { - - /* - ********************************************************************** - * - * CALCULATION - * org.solovyev.android.calculator.CalculatorEvaluationEventData - * - ********************************************************************** - */ - - - // @NotNull CalculatorEditorViewState - manual_calculation_requested, - - // @NotNull org.solovyev.android.calculator.CalculatorInput - calculation_started, - - // @NotNull org.solovyev.android.calculator.CalculatorOutput - calculation_result, - - calculation_cancelled, - - // @NotNull org.solovyev.android.calculator.CalculatorFailure - calculation_failed, - - calculation_finished, - - /* - ********************************************************************** - * - * CONVERSION - * CalculatorConversionEventData - * - ********************************************************************** - */ - conversion_started, - - // @NotNull String conversion result - conversion_result, - - // @NotNull ConversionFailure - conversion_failed, - - conversion_finished, - - /* - ********************************************************************** - * - * EDITOR - * - ********************************************************************** - */ - - // @NotNull org.solovyev.android.calculator.CalculatorEditorChangeEventData - editor_state_changed, - - // @NotNull CalculatorDisplayChangeEventData - display_state_changed, - - /* - ********************************************************************** - * - * ENGINE - * - ********************************************************************** - */ - - engine_preferences_changed, - - /* - ********************************************************************** - * - * HISTORY - * - ********************************************************************** - */ - - // @NotNull CalculatorHistoryState - history_state_added, - - // @NotNull CalculatorHistoryState - use_history_state, - - clear_history_requested, - - /* - ********************************************************************** - * - * MATH ENTITIES - * - ********************************************************************** - */ - - // @NotNull IConstant - use_constant, - - // @NotNull Function - use_function, - - // @NotNull Operator - use_operator, - - // @NotNull IConstant - constant_added, - - // @NotNull Change - constant_changed, - - // @NotNull IConstant - constant_removed; - - 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 { + + /* + ********************************************************************** + * + * CALCULATION + * org.solovyev.android.calculator.CalculatorEvaluationEventData + * + ********************************************************************** + */ + + + // @NotNull CalculatorEditorViewState + manual_calculation_requested, + + // @NotNull org.solovyev.android.calculator.CalculatorOutput + calculation_result, + + calculation_cancelled, + + // @NotNull org.solovyev.android.calculator.CalculatorFailure + calculation_failed, + + /* + ********************************************************************** + * + * CONVERSION + * CalculatorConversionEventData + * + ********************************************************************** + */ + conversion_started, + + // @NotNull String conversion result + conversion_result, + + // @NotNull ConversionFailure + conversion_failed, + + conversion_finished, + + /* + ********************************************************************** + * + * EDITOR + * + ********************************************************************** + */ + + // @NotNull org.solovyev.android.calculator.CalculatorEditorChangeEventData + editor_state_changed, + + // @NotNull CalculatorDisplayChangeEventData + display_state_changed, + + /* + ********************************************************************** + * + * ENGINE + * + ********************************************************************** + */ + + engine_preferences_changed, + + /* + ********************************************************************** + * + * HISTORY + * + ********************************************************************** + */ + + // @NotNull CalculatorHistoryState + history_state_added, + + // @NotNull CalculatorHistoryState + use_history_state, + + clear_history_requested, + + /* + ********************************************************************** + * + * MATH ENTITIES + * + ********************************************************************** + */ + + // @NotNull IConstant + use_constant, + + // @NotNull Function + use_function, + + // @NotNull Operator + use_operator, + + // @NotNull IConstant + constant_added, + + // @NotNull Change + constant_changed, + + // @NotNull IConstant + constant_removed; + + 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 0e80f9bc..0d16e859 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,474 +1,470 @@ -package org.solovyev.android.calculator; - -import jscl.AbstractJsclArithmeticException; -import jscl.NumeralBase; -import jscl.NumeralBaseException; -import jscl.math.Generic; -import jscl.math.function.Function; -import jscl.math.function.IConstant; -import jscl.math.operator.Operator; -import jscl.text.ParseInterruptedException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.history.CalculatorHistory; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.android.calculator.units.CalculatorNumeralBase; -import org.solovyev.common.history.HistoryAction; -import org.solovyev.common.msg.MessageRegistry; -import org.solovyev.common.msg.MessageType; -import org.solovyev.common.text.StringUtils; -import org.solovyev.math.units.ConversionException; -import org.solovyev.math.units.ConversionUtils; - -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, CalculatorEventListener { - - @NotNull - private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); - - @NotNull - private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID); - - @NotNull - private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); - - @NotNull - private final Executor calculationsExecutor = Executors.newFixedThreadPool(10); - - // NOTE: only one thread is responsible for events as all events must be done in order of their creating - @NotNull - private final Executor eventExecutor = Executors.newFixedThreadPool(1); - - public CalculatorImpl() { - this.addCalculatorEventListener(this); - } - - @NotNull - private CalculatorEventData nextEventData() { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataImpl.newInstance(eventId, eventId); - } - - @NotNull - private CalculatorEventData nextEventData(@NotNull Object source) { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataImpl.newInstance(eventId, eventId, source); - } - - @NotNull - private CalculatorEventData nextEventData(@NotNull Long sequenceId) { - long eventId = counter.incrementAndGet(); - return CalculatorEventDataImpl.newInstance(eventId, sequenceId); - } - - /* - ********************************************************************** - * - * CALCULATION - * - ********************************************************************** - */ - - @Override - public void evaluate() { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.numeric, viewState.getText()); - } - - @Override - public void evaluate(@NotNull Long sequenceId) { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); - this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); - } - - @Override - public void simplify() { - final CalculatorEditorViewState viewState = getEditor().getViewState(); - fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.simplify, viewState.getText()); - } - - @NotNull - @Override - public CalculatorEventData evaluate(@NotNull final JsclOperation operation, - @NotNull final String expression) { - - final CalculatorEventData eventDataId = nextEventData(); - - calculationsExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); - } - }); - - return eventDataId; - } - - @NotNull - @Override - public CalculatorEventData evaluate(@NotNull final JsclOperation operation, @NotNull final String expression, @NotNull Long sequenceId) { - final CalculatorEventData eventDataId = nextEventData(sequenceId); - - calculationsExecutor.execute(new Runnable() { - @Override - public void run() { - CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); - } - }); - - return eventDataId; - } - - @Override - public void init() { - CalculatorLocatorImpl.getInstance().getEngine().init(); - CalculatorLocatorImpl.getInstance().getHistory().load(); - } - - @NotNull - private CalculatorConversionEventData newConversionEventData(@NotNull Long sequenceId, - @NotNull Generic value, - @NotNull NumeralBase from, - @NotNull NumeralBase to, - @NotNull CalculatorDisplayViewState displayViewState) { - return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState); - } - - private void evaluate(@NotNull Long sequenceId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr) { - - PreparedExpression preparedExpression = null; - - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_started, new CalculatorInputImpl(expression, operation)); - - try { - - expression = expression.trim(); - - if (StringUtils.isEmpty(expression)) { - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation)); - } else { - preparedExpression = preprocessor.process(expression); - - final String jsclExpression = preparedExpression.toString(); - - try { - - final Generic result = operation.evaluateGeneric(jsclExpression, CalculatorLocatorImpl.getInstance().getEngine().getMathEngine()); - - // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) - result.toString(); - - final CalculatorOutput data = CalculatorOutputImpl.newOutput(operation.getFromProcessor().process(result), operation, result); - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data); - - } 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(nextEventData(calculationId), operation, expression); - } - - private void handleException(@NotNull Long sequenceId, - @NotNull JsclOperation operation, - @NotNull String expression, - @Nullable MessageRegistry mr, - @Nullable PreparedExpression preparedExpression, - @NotNull CalculatorParseException parseException) { - - if (operation == JsclOperation.numeric - && preparedExpression != null - && preparedExpression.isExistsUndefinedVar()) { - - evaluate(sequenceId, JsclOperation.simplify, expression, mr); - } else { - - fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), 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)); - } - - /* - ********************************************************************** - * - * CONVERSION - * - ********************************************************************** - */ - - @NotNull - @Override - public CalculatorEventData convert(@NotNull final Generic value, - @NotNull final NumeralBase to) { - final CalculatorEventData eventDataId = nextEventData(); - - final CalculatorDisplayViewState displayViewState = CalculatorLocatorImpl.getInstance().getDisplay().getViewState(); - final NumeralBase from = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase(); - - calculationsExecutor.execute(new Runnable() { - @Override - public void run() { - final Long sequenceId = eventDataId.getSequenceId(); - - fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null); - try { - - final String result = doConversion(value, from, to); - - fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result); - - } catch (ConversionException e) { - fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e)); - } - } - }); - - return eventDataId; - } - - @NotNull - private static String doConversion(@NotNull Generic generic, - @NotNull NumeralBase from, - @NotNull NumeralBase to) throws ConversionException { - final String result; - - 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 - } - } - - result = ConversionUtils.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to)); - } else { - result = generic.toString(); - } - - return result; - } - - @Override - public boolean isConversionPossible(@NotNull Generic generic, NumeralBase from, @NotNull NumeralBase to) { - try { - doConversion(generic, from, to); - return true; - } catch (ConversionException e) { - return false; - } - } - - /* - ********************************************************************** - * - * 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 final CalculatorEventData calculatorEventData, @NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { - eventExecutor.execute(new Runnable() { - @Override - public void run() { - calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); - } - }); - } - - @Override - public void fireCalculatorEvents(@NotNull final List calculatorEvents) { - eventExecutor.execute(new Runnable() { - @Override - public void run() { - calculatorEventContainer.fireCalculatorEvents(calculatorEvents); - } - }); - } - - @NotNull - @Override - public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { - final CalculatorEventData eventData = nextEventData(); - - fireCalculatorEvent(eventData, calculatorEventType, data); - - return eventData; - } - - @NotNull - @Override - public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Object source) { - final CalculatorEventData eventData = nextEventData(source); - - fireCalculatorEvent(eventData, calculatorEventType, data); - - return eventData; - } - - @NotNull - @Override - public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Long sequenceId) { - final CalculatorEventData eventData = nextEventData(sequenceId); - - fireCalculatorEvent(eventData, calculatorEventType, data); - - return eventData; - } - - /* - ********************************************************************** - * - * EVENTS HANDLER - * - ********************************************************************** - */ - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - - switch (calculatorEventType) { - case editor_state_changed: - final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data; - - final String newText = changeEventData.getNewValue().getText(); - final String oldText = changeEventData.getOldValue().getText(); - - if (!newText.equals(oldText)) { - evaluate(JsclOperation.numeric, changeEventData.getNewValue().getText(), calculatorEventData.getSequenceId()); - } - break; - - case engine_preferences_changed: - evaluate(calculatorEventData.getSequenceId()); - break; - - case use_constant: - final IConstant constant = (IConstant)data; - CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(constant.getName()); - break; - - case use_operator: - final Operator operator = (Operator)data; - CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(operator.getName()); - break; - - case use_function: - final Function function = (Function)data; - CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(function.getName()); - break; - - } - } - - /* - ********************************************************************** - * - * HISTORY - * - ********************************************************************** - */ - - @Override - public void doHistoryAction(@NotNull HistoryAction historyAction) { - final CalculatorHistory history = CalculatorLocatorImpl.getInstance().getHistory(); - if (history.isActionAvailable(historyAction)) { - final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState()); - if (newState != null) { - setCurrentHistoryState(newState); - } - } - } - - @Override - public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { - editorHistoryState.setValuesFromHistory(getEditor(), getDisplay()); - } - - @NotNull - @Override - public CalculatorHistoryState getCurrentHistoryState() { - return CalculatorHistoryState.newInstance(getEditor(), getDisplay()); - } - - /* - ********************************************************************** - * - * OTHER - * - ********************************************************************** - */ - - @NotNull - private CalculatorEditor getEditor() { - return CalculatorLocatorImpl.getInstance().getEditor(); - } - - @NotNull - private CalculatorDisplay getDisplay() { - return CalculatorLocatorImpl.getInstance().getDisplay(); - } -} +package org.solovyev.android.calculator; + +import jscl.AbstractJsclArithmeticException; +import jscl.NumeralBase; +import jscl.NumeralBaseException; +import jscl.math.Generic; +import jscl.math.function.Function; +import jscl.math.function.IConstant; +import jscl.math.operator.Operator; +import jscl.text.ParseInterruptedException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.history.CalculatorHistory; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.text.TextProcessor; +import org.solovyev.android.calculator.units.CalculatorNumeralBase; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.msg.MessageRegistry; +import org.solovyev.common.msg.MessageType; +import org.solovyev.common.text.StringUtils; +import org.solovyev.math.units.ConversionException; +import org.solovyev.math.units.ConversionUtils; + +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, CalculatorEventListener { + + @NotNull + private final CalculatorEventContainer calculatorEventContainer = new ListCalculatorEventContainer(); + + @NotNull + private final AtomicLong counter = new AtomicLong(CalculatorUtils.FIRST_ID); + + @NotNull + private final TextProcessor preprocessor = ToJsclTextProcessor.getInstance(); + + @NotNull + private final Executor calculationsExecutor = Executors.newFixedThreadPool(10); + + // NOTE: only one thread is responsible for events as all events must be done in order of their creating + @NotNull + private final Executor eventExecutor = Executors.newFixedThreadPool(1); + + public CalculatorImpl() { + this.addCalculatorEventListener(this); + } + + @NotNull + private CalculatorEventData nextEventData() { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataImpl.newInstance(eventId, eventId); + } + + @NotNull + private CalculatorEventData nextEventData(@NotNull Object source) { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataImpl.newInstance(eventId, eventId, source); + } + + @NotNull + private CalculatorEventData nextEventData(@NotNull Long sequenceId) { + long eventId = counter.incrementAndGet(); + return CalculatorEventDataImpl.newInstance(eventId, sequenceId); + } + + /* + ********************************************************************** + * + * CALCULATION + * + ********************************************************************** + */ + + @Override + public void evaluate() { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); + this.evaluate(JsclOperation.numeric, viewState.getText()); + } + + @Override + public void evaluate(@NotNull Long sequenceId) { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); + this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); + } + + @Override + public void simplify() { + final CalculatorEditorViewState viewState = getEditor().getViewState(); + fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); + this.evaluate(JsclOperation.simplify, viewState.getText()); + } + + @NotNull + @Override + public CalculatorEventData evaluate(@NotNull final JsclOperation operation, + @NotNull final String expression) { + + final CalculatorEventData eventDataId = nextEventData(); + + calculationsExecutor.execute(new Runnable() { + @Override + public void run() { + CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); + } + }); + + return eventDataId; + } + + @NotNull + @Override + public CalculatorEventData evaluate(@NotNull final JsclOperation operation, @NotNull final String expression, @NotNull Long sequenceId) { + final CalculatorEventData eventDataId = nextEventData(sequenceId); + + calculationsExecutor.execute(new Runnable() { + @Override + public void run() { + CalculatorImpl.this.evaluate(eventDataId.getSequenceId(), operation, expression, null); + } + }); + + return eventDataId; + } + + @Override + public void init() { + CalculatorLocatorImpl.getInstance().getEngine().init(); + CalculatorLocatorImpl.getInstance().getHistory().load(); + } + + @NotNull + private CalculatorConversionEventData newConversionEventData(@NotNull Long sequenceId, + @NotNull Generic value, + @NotNull NumeralBase from, + @NotNull NumeralBase to, + @NotNull CalculatorDisplayViewState displayViewState) { + return CalculatorConversionEventDataImpl.newInstance(nextEventData(sequenceId), value, from, to, displayViewState); + } + + private void evaluate(@NotNull Long sequenceId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr) { + + PreparedExpression preparedExpression = null; + + try { + + expression = expression.trim(); + + if (StringUtils.isEmpty(expression)) { + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, CalculatorOutputImpl.newEmptyOutput(operation)); + } else { + preparedExpression = preprocessor.process(expression); + + final String jsclExpression = preparedExpression.toString(); + + try { + + final Generic result = operation.evaluateGeneric(jsclExpression, CalculatorLocatorImpl.getInstance().getEngine().getMathEngine()); + + // NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!) + result.toString(); + + final CalculatorOutput data = CalculatorOutputImpl.newOutput(operation.getFromProcessor().process(result), operation, result); + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_result, data); + + } 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); + } + } + + @NotNull + private CalculatorEventData newCalculationEventData(@NotNull JsclOperation operation, + @NotNull String expression, + @NotNull Long calculationId) { + return new CalculatorEvaluationEventDataImpl(nextEventData(calculationId), operation, expression); + } + + private void handleException(@NotNull Long sequenceId, + @NotNull JsclOperation operation, + @NotNull String expression, + @Nullable MessageRegistry mr, + @Nullable PreparedExpression preparedExpression, + @NotNull CalculatorParseException parseException) { + + if (operation == JsclOperation.numeric + && preparedExpression != null + && preparedExpression.isExistsUndefinedVar()) { + + evaluate(sequenceId, JsclOperation.simplify, expression, mr); + } else { + + fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), 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); + } else { + fireCalculatorEvent(newCalculationEventData(operation, expression, calculationId), CalculatorEventType.calculation_failed, new CalculatorFailureImpl(evalException)); + } + } + + /* + ********************************************************************** + * + * CONVERSION + * + ********************************************************************** + */ + + @NotNull + @Override + public CalculatorEventData convert(@NotNull final Generic value, + @NotNull final NumeralBase to) { + final CalculatorEventData eventDataId = nextEventData(); + + final CalculatorDisplayViewState displayViewState = CalculatorLocatorImpl.getInstance().getDisplay().getViewState(); + final NumeralBase from = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase(); + + calculationsExecutor.execute(new Runnable() { + @Override + public void run() { + final Long sequenceId = eventDataId.getSequenceId(); + + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_started, null); + try { + + final String result = doConversion(value, from, to); + + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_result, result); + + } catch (ConversionException e) { + fireCalculatorEvent(newConversionEventData(sequenceId, value, from, to, displayViewState), CalculatorEventType.conversion_failed, new ConversionFailureImpl(e)); + } + } + }); + + return eventDataId; + } + + @NotNull + private static String doConversion(@NotNull Generic generic, + @NotNull NumeralBase from, + @NotNull NumeralBase to) throws ConversionException { + final String result; + + 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 + } + } + + result = ConversionUtils.doConversion(CalculatorNumeralBase.getConverter(), fromString, CalculatorNumeralBase.valueOf(from), CalculatorNumeralBase.valueOf(to)); + } else { + result = generic.toString(); + } + + return result; + } + + @Override + public boolean isConversionPossible(@NotNull Generic generic, NumeralBase from, @NotNull NumeralBase to) { + try { + doConversion(generic, from, to); + return true; + } catch (ConversionException e) { + return false; + } + } + + /* + ********************************************************************** + * + * 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 final CalculatorEventData calculatorEventData, @NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { + eventExecutor.execute(new Runnable() { + @Override + public void run() { + calculatorEventContainer.fireCalculatorEvent(calculatorEventData, calculatorEventType, data); + } + }); + } + + @Override + public void fireCalculatorEvents(@NotNull final List calculatorEvents) { + eventExecutor.execute(new Runnable() { + @Override + public void run() { + calculatorEventContainer.fireCalculatorEvents(calculatorEvents); + } + }); + } + + @NotNull + @Override + public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data) { + final CalculatorEventData eventData = nextEventData(); + + fireCalculatorEvent(eventData, calculatorEventType, data); + + return eventData; + } + + @NotNull + @Override + public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Object source) { + final CalculatorEventData eventData = nextEventData(source); + + fireCalculatorEvent(eventData, calculatorEventType, data); + + return eventData; + } + + @NotNull + @Override + public CalculatorEventData fireCalculatorEvent(@NotNull final CalculatorEventType calculatorEventType, @Nullable final Object data, @NotNull Long sequenceId) { + final CalculatorEventData eventData = nextEventData(sequenceId); + + fireCalculatorEvent(eventData, calculatorEventType, data); + + return eventData; + } + + /* + ********************************************************************** + * + * EVENTS HANDLER + * + ********************************************************************** + */ + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + + switch (calculatorEventType) { + case editor_state_changed: + final CalculatorEditorChangeEventData changeEventData = (CalculatorEditorChangeEventData) data; + + final String newText = changeEventData.getNewValue().getText(); + final String oldText = changeEventData.getOldValue().getText(); + + if (!newText.equals(oldText)) { + evaluate(JsclOperation.numeric, changeEventData.getNewValue().getText(), calculatorEventData.getSequenceId()); + } + break; + + case engine_preferences_changed: + evaluate(calculatorEventData.getSequenceId()); + break; + + case use_constant: + final IConstant constant = (IConstant)data; + CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(constant.getName()); + break; + + case use_operator: + final Operator operator = (Operator)data; + CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(operator.getName()); + break; + + case use_function: + final Function function = (Function)data; + CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(function.getName()); + break; + + } + } + + /* + ********************************************************************** + * + * HISTORY + * + ********************************************************************** + */ + + @Override + public void doHistoryAction(@NotNull HistoryAction historyAction) { + final CalculatorHistory history = CalculatorLocatorImpl.getInstance().getHistory(); + if (history.isActionAvailable(historyAction)) { + final CalculatorHistoryState newState = history.doAction(historyAction, getCurrentHistoryState()); + if (newState != null) { + setCurrentHistoryState(newState); + } + } + } + + @Override + public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) { + editorHistoryState.setValuesFromHistory(getEditor(), getDisplay()); + } + + @NotNull + @Override + public CalculatorHistoryState getCurrentHistoryState() { + return CalculatorHistoryState.newInstance(getEditor(), getDisplay()); + } + + /* + ********************************************************************** + * + * OTHER + * + ********************************************************************** + */ + + @NotNull + private CalculatorEditor getEditor() { + return CalculatorLocatorImpl.getInstance().getEditor(); + } + + @NotNull + private CalculatorDisplay getDisplay() { + return CalculatorLocatorImpl.getInstance().getDisplay(); + } +} 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 index 0431dfb5..6f65ac48 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java @@ -1,113 +1,113 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.history.CalculatorHistory; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 12:45 - */ -public class CalculatorLocatorImpl implements CalculatorLocator { - - @NotNull - private CalculatorEngine calculatorEngine; - - @NotNull - private Calculator calculator; - - @NotNull - private CalculatorEditor calculatorEditor; - - @NotNull - private CalculatorDisplay calculatorDisplay; - - @NotNull - private CalculatorKeyboard calculatorKeyboard; - - @NotNull - private CalculatorHistory calculatorHistory; - - @NotNull - private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier(); - - @NotNull - private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard(); - - @NotNull - private static final CalculatorLocator instance = new CalculatorLocatorImpl(); - - private CalculatorLocatorImpl() { - } - - @Override - public void init(@NotNull Calculator calculator, - @NotNull CalculatorEngine engine, - @NotNull CalculatorClipboard clipboard, - @NotNull CalculatorNotifier notifier, - @NotNull CalculatorHistory history) { - - this.calculator = calculator; - this.calculatorEngine = engine; - this.calculatorClipboard = clipboard; - this.calculatorNotifier = notifier; - this.calculatorHistory = history; - - calculatorEditor = new CalculatorEditorImpl(this.calculator); - calculatorDisplay = new CalculatorDisplayImpl(this.calculator); - calculatorKeyboard = new CalculatorKeyboardImpl(this.calculator); - } - - @NotNull - public static CalculatorLocator getInstance() { - return instance; - } - - @NotNull - @Override - public CalculatorEngine getEngine() { - return calculatorEngine; - } - - @NotNull - @Override - public Calculator getCalculator() { - return this.calculator; - } - - @Override - @NotNull - public CalculatorDisplay getDisplay() { - return calculatorDisplay; - } - - @NotNull - @Override - public CalculatorEditor getEditor() { - return calculatorEditor; - } - - @Override - @NotNull - public CalculatorKeyboard getKeyboard() { - return calculatorKeyboard; - } - - @Override - @NotNull - public CalculatorClipboard getClipboard() { - return calculatorClipboard; - } - - @Override - @NotNull - public CalculatorNotifier getNotifier() { - return calculatorNotifier; - } - - @Override - @NotNull - public CalculatorHistory getHistory() { - return calculatorHistory; - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.history.CalculatorHistory; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 12:45 + */ +public class CalculatorLocatorImpl implements CalculatorLocator { + + @NotNull + private CalculatorEngine calculatorEngine; + + @NotNull + private Calculator calculator; + + @NotNull + private CalculatorEditor calculatorEditor; + + @NotNull + private CalculatorDisplay calculatorDisplay; + + @NotNull + private CalculatorKeyboard calculatorKeyboard; + + @NotNull + private CalculatorHistory calculatorHistory; + + @NotNull + private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier(); + + @NotNull + private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard(); + + @NotNull + private static final CalculatorLocator instance = new CalculatorLocatorImpl(); + + public CalculatorLocatorImpl() { + } + + @Override + public void init(@NotNull Calculator calculator, + @NotNull CalculatorEngine engine, + @NotNull CalculatorClipboard clipboard, + @NotNull CalculatorNotifier notifier, + @NotNull CalculatorHistory history) { + + this.calculator = calculator; + this.calculatorEngine = engine; + this.calculatorClipboard = clipboard; + this.calculatorNotifier = notifier; + this.calculatorHistory = history; + + calculatorEditor = new CalculatorEditorImpl(this.calculator); + calculatorDisplay = new CalculatorDisplayImpl(this.calculator); + calculatorKeyboard = new CalculatorKeyboardImpl(this.calculator); + } + + @NotNull + public static CalculatorLocator getInstance() { + return instance; + } + + @NotNull + @Override + public CalculatorEngine getEngine() { + return calculatorEngine; + } + + @NotNull + @Override + public Calculator getCalculator() { + return this.calculator; + } + + @Override + @NotNull + public CalculatorDisplay getDisplay() { + return calculatorDisplay; + } + + @NotNull + @Override + public CalculatorEditor getEditor() { + return calculatorEditor; + } + + @Override + @NotNull + public CalculatorKeyboard getKeyboard() { + return calculatorKeyboard; + } + + @Override + @NotNull + public CalculatorClipboard getClipboard() { + return calculatorClipboard; + } + + @Override + @NotNull + public CalculatorNotifier getNotifier() { + return calculatorNotifier; + } + + @Override + @NotNull + public CalculatorHistory getHistory() { + return calculatorHistory; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java index 9c3973ad..675b5960 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/History.java @@ -21,7 +21,7 @@ import java.util.List; @Root public class History { - @ElementList + @ElementList(type = CalculatorHistoryState.class) private List historyItems = new ArrayList(); public History() { diff --git a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java index 3f538770..9cf2c346 100644 --- a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java +++ b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java @@ -1,33 +1,138 @@ -package org.solovyev.android.calculator; - -import jscl.JsclMathEngine; -import org.jetbrains.annotations.NotNull; -import org.mockito.Mockito; -import org.solovyev.android.calculator.history.CalculatorHistory; - -/** - * User: serso - * Date: 10/7/12 - * Time: 8:40 PM - */ -public class CalculatorTestUtils { - - public static void staticSetUp() throws Exception { - CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class)); - CalculatorLocatorImpl.getInstance().getEngine().init(); - } - - @NotNull - static CalculatorEngineImpl newCalculatorEngine() { - final MathEntityDao mathEntityDao = Mockito.mock(MathEntityDao.class); - - final JsclMathEngine jsclEngine = JsclMathEngine.getInstance(); - - final CalculatorVarsRegistry varsRegistry = new CalculatorVarsRegistry(jsclEngine.getConstantsRegistry(), mathEntityDao); - final CalculatorFunctionsMathRegistry functionsRegistry = new CalculatorFunctionsMathRegistry(jsclEngine.getFunctionsRegistry(), mathEntityDao); - final CalculatorOperatorsMathRegistry operatorsRegistry = new CalculatorOperatorsMathRegistry(jsclEngine.getOperatorsRegistry(), mathEntityDao); - final CalculatorPostfixFunctionsRegistry postfixFunctionsRegistry = new CalculatorPostfixFunctionsRegistry(jsclEngine.getPostfixFunctionsRegistry(), mathEntityDao); - - return new CalculatorEngineImpl(jsclEngine, varsRegistry, functionsRegistry, operatorsRegistry, postfixFunctionsRegistry, null); - } -} +package org.solovyev.android.calculator; + +import jscl.JsclMathEngine; +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.mockito.Mockito; +import org.solovyev.android.calculator.history.CalculatorHistory; +import org.solovyev.android.calculator.jscl.JsclOperation; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * User: serso + * Date: 10/7/12 + * Time: 8:40 PM + */ +public class CalculatorTestUtils { + + // in seconds + public static final int TIMEOUT = 1000; + + public static void staticSetUp() throws Exception { + CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class)); + CalculatorLocatorImpl.getInstance().getEngine().init(); + } + + @NotNull + static CalculatorEngineImpl newCalculatorEngine() { + final MathEntityDao mathEntityDao = Mockito.mock(MathEntityDao.class); + + final JsclMathEngine jsclEngine = JsclMathEngine.getInstance(); + + final CalculatorVarsRegistry varsRegistry = new CalculatorVarsRegistry(jsclEngine.getConstantsRegistry(), mathEntityDao); + final CalculatorFunctionsMathRegistry functionsRegistry = new CalculatorFunctionsMathRegistry(jsclEngine.getFunctionsRegistry(), mathEntityDao); + final CalculatorOperatorsMathRegistry operatorsRegistry = new CalculatorOperatorsMathRegistry(jsclEngine.getOperatorsRegistry(), mathEntityDao); + final CalculatorPostfixFunctionsRegistry postfixFunctionsRegistry = new CalculatorPostfixFunctionsRegistry(jsclEngine.getPostfixFunctionsRegistry(), mathEntityDao); + + return new CalculatorEngineImpl(jsclEngine, varsRegistry, functionsRegistry, operatorsRegistry, postfixFunctionsRegistry, null); + } + + public static void assertEval(@NotNull String expected, @NotNull String expression) { + assertEval(expected, expression, JsclOperation.numeric); + } + + public static void assertEval(@NotNull String expected, @NotNull String expression, @NotNull JsclOperation operation) { + final Calculator calculator = CalculatorLocatorImpl.getInstance().getCalculator(); + + CalculatorLocatorImpl.getInstance().getDisplay().setViewState(CalculatorDisplayViewStateImpl.newDefaultInstance()); + + final CountDownLatch latch = new CountDownLatch(1); + final TestCalculatorEventListener calculatorEventListener = new TestCalculatorEventListener(latch); + try { + calculator.addCalculatorEventListener(calculatorEventListener); + calculatorEventListener.setCalculatorEventData(calculator.evaluate(operation, expression)); + + if (latch.await(TIMEOUT, TimeUnit.SECONDS)) { + Assert.assertNotNull(calculatorEventListener.getResult()); + Assert.assertEquals(expected, calculatorEventListener.getResult().getText()); + } else { + Assert.fail("Too long wait for: " + expression); + } + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + calculator.removeCalculatorEventListener(calculatorEventListener); + } + } + + public static void assertError(@NotNull String expression) { + assertError(expression, JsclOperation.numeric); + } + + private static final class TestCalculatorEventListener implements CalculatorEventListener { + + @Nullable + private CalculatorEventData calculatorEventData; + + @NotNull + private final CountDownLatch latch; + + @Nullable + private volatile CalculatorDisplayViewState result = null; + + public TestCalculatorEventListener(@NotNull CountDownLatch latch) { + this.latch = latch; + } + + public void setCalculatorEventData(@Nullable CalculatorEventData calculatorEventData) { + this.calculatorEventData = calculatorEventData; + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + if ( this.calculatorEventData != null && calculatorEventData.isSameSequence(this.calculatorEventData) ) { + if ( calculatorEventType == CalculatorEventType.display_state_changed ) { + final CalculatorDisplayChangeEventData displayChange = (CalculatorDisplayChangeEventData)data; + + result = displayChange.getNewValue(); + + latch.countDown(); + } + } + } + + @Nullable + public CalculatorDisplayViewState getResult() { + return result; + } + } + + public static void assertError(@NotNull String expression, @NotNull JsclOperation operation) { + final Calculator calculator = CalculatorLocatorImpl.getInstance().getCalculator(); + + CalculatorLocatorImpl.getInstance().getDisplay().setViewState(CalculatorDisplayViewStateImpl.newDefaultInstance()); + + final CountDownLatch latch = new CountDownLatch(1); + final TestCalculatorEventListener calculatorEventListener = new TestCalculatorEventListener(latch); + try { + calculator.addCalculatorEventListener(calculatorEventListener); + calculatorEventListener.setCalculatorEventData(calculator.evaluate(operation, expression)); + + if (latch.await(TIMEOUT, TimeUnit.SECONDS)) { + Assert.assertNotNull(calculatorEventListener.getResult()); + Assert.assertFalse(calculatorEventListener.getResult().isValid()); + } else { + Assert.fail("Too long wait for: " + expression); + } + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + calculator.removeCalculatorEventListener(calculatorEventListener); + } + } +} diff --git a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/model/AndroidCalculatorEngineTest.java b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/model/AndroidCalculatorEngineTest.java index edffffd9..44692471 100644 --- a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/model/AndroidCalculatorEngineTest.java +++ b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/model/AndroidCalculatorEngineTest.java @@ -1,448 +1,426 @@ -/* - * 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.MathEngine; -import jscl.NumeralBase; -import jscl.math.Expression; -import jscl.math.Generic; -import jscl.math.function.Constant; -import jscl.math.function.CustomFunction; -import jscl.text.ParseException; -import junit.framework.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.solovyev.android.calculator.CalculatorEvalException; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.CalculatorTestUtils; - -import java.text.DecimalFormatSymbols; -import java.util.Locale; - -import static junit.framework.Assert.fail; - -/** - * User: serso - * Date: 9/17/11 - * Time: 9:47 PM - */ - -@SuppressWarnings("deprecation") -public class AndroidCalculatorEngineTest { - - @BeforeClass - public static void setUp() throws Exception { - CalculatorTestUtils.staticSetUp(); - CalculatorLocatorImpl.getInstance().getEngine().setPrecision(3); - } - - - @Test - public void testDegrees() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - final AngleUnit defaultAngleUnit = cm.getAngleUnits(); - try { - cm.setAngleUnits(AngleUnit.rad); - cm.setPrecision(3); - try { - Assert.assertEquals("0.017", cm.evaluate("°")); - fail(); - } catch (ParseException e) { - - } - - Assert.assertEquals("0.017", cm.evaluate( "1°")); - Assert.assertEquals("0.349", cm.evaluate( "20.0°")); - Assert.assertEquals("0.5", cm.evaluate( "sin(30°)")); - Assert.assertEquals("0.524", cm.evaluate( "asin(sin(30°))")); - Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.evaluate( "∂(cos(t),t,t,1°)")); - - Assert.assertEquals("∂(cos(t), t, t, 1°)", cm.simplify("∂(cos(t),t,t,1°)")); - } finally { - cm.setAngleUnits(defaultAngleUnit); - } - } - -/* @Test - public void testLongExecution() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - try { - cm.evaluate( "3^10^10^10"); - fail(); - } catch (ParseException e) { - if (e.getMessageCode().equals(Messages.msg_3)) { - - } else { - System.out.print(e.getCause().getMessage()); - fail(); - } - } - - try { - cm.evaluate("9999999!"); - fail(); - } catch (ParseException e) { - if (e.getMessageCode().equals(Messages.msg_3)) { - - } else { - System.out.print(e.getCause().getMessage()); - fail(); - } - } - - final long start = System.currentTimeMillis(); - try { - cm.evaluate( "3^10^10^10"); - fail(); - } catch (ParseException e) { - if (e.getMessage().startsWith("Too long calculation")) { - final long end = System.currentTimeMillis(); - Assert.assertTrue(end - start < 1000); - } else { - fail(); - } - } - - }*/ - - @Test - public void testEvaluate() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - Assert.assertEquals("cos(t)+10%", cm.simplify( "cos(t)+10%")); - - final Generic expression = cm.simplifyGeneric("cos(t)+10%"); - expression.substitute(new Constant("t"), Expression.valueOf(100d)); - - Assert.assertEquals("it", cm.simplify( "it")); - Assert.assertEquals("10%", cm.simplify( "10%")); - Assert.assertEquals("0", cm.evaluate( "eq(0, 1)")); - Assert.assertEquals("1", cm.evaluate( "eq(1, 1)")); - Assert.assertEquals("1", cm.evaluate( "eq( 1, 1)")); - Assert.assertEquals("1", cm.simplify( "eq( 1, 1)")); - Assert.assertEquals("1", cm.evaluate( "lg(10)")); - Assert.assertEquals("4", cm.evaluate( "2+2")); - final AngleUnit defaultAngleUnit = cm.getAngleUnits(); - try { - cm.setAngleUnits(AngleUnit.rad); - Assert.assertEquals("-0.757", cm.evaluate( "sin(4)")); - Assert.assertEquals("0.524", cm.evaluate( "asin(0.5)")); - Assert.assertEquals("-0.396", cm.evaluate( "sin(4)asin(0.5)")); - Assert.assertEquals("-0.56", cm.evaluate( "sin(4)asin(0.5)√(2)")); - Assert.assertEquals("-0.56", cm.evaluate( "sin(4)asin(0.5)√(2)")); - } finally { - cm.setAngleUnits(defaultAngleUnit); - } - Assert.assertEquals("7.389", cm.evaluate( "e^2")); - Assert.assertEquals("7.389", cm.evaluate( "exp(1)^2")); - Assert.assertEquals("7.389", cm.evaluate( "exp(2)")); - Assert.assertEquals("2+i", cm.evaluate( "2*1+√(-1)")); - try { - cm.setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.921+Πi", cm.evaluate( "ln(5cosh(38π√(2cos(2))))")); - Assert.assertEquals("-3.41+3.41i", cm.evaluate( "(5tan(2i)+2i)/(1-i)")); - } finally { - cm.setAngleUnits(defaultAngleUnit); - } - Assert.assertEquals("7.389i", cm.evaluate( "iexp(2)")); - Assert.assertEquals("2+7.389i", cm.evaluate( "2+iexp(2)")); - Assert.assertEquals("2+7.389i", cm.evaluate( "2+√(-1)exp(2)")); - Assert.assertEquals("2-2.5i", cm.evaluate( "2-2.5i")); - Assert.assertEquals("-2-2.5i", cm.evaluate( "-2-2.5i")); - Assert.assertEquals("-2+2.5i", cm.evaluate( "-2+2.5i")); - Assert.assertEquals("-2+2.1i", cm.evaluate( "-2+2.1i")); - Assert.assertEquals("-0.1-0.2i", cm.evaluate( "(1-i)/(2+6i)")); - - junit.framework.Assert.assertEquals("24", cm.evaluate( "4!")); - junit.framework.Assert.assertEquals("24", cm.evaluate( "(2+2)!")); - junit.framework.Assert.assertEquals("120", cm.evaluate( "(2+2+1)!")); - junit.framework.Assert.assertEquals("24", cm.evaluate( "(2.0+2.0)!")); - junit.framework.Assert.assertEquals("24", cm.evaluate( "4.0!")); - junit.framework.Assert.assertEquals("720", cm.evaluate( "(3!)!")); - 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( "i!")); - fail(); - } catch (ParseException e) { - } - - junit.framework.Assert.assertEquals("1", cm.evaluate( "(π/π)!")); - - try { - junit.framework.Assert.assertEquals("i", cm.evaluate( "(-1)i!")); - fail(); - } catch (ParseException e) { - - } - junit.framework.Assert.assertEquals("24i", cm.evaluate( "4!i")); - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("si", 5d)); - - try { - cm.setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.451", cm.evaluate( "acos(0.8999999999999811)")); - Assert.assertEquals("-0.959", cm.evaluate( "sin(5)")); - Assert.assertEquals("-4.795", cm.evaluate( "sin(5)si")); - Assert.assertEquals("-23.973", cm.evaluate( "sisin(5)si")); - Assert.assertEquals("-23.973", cm.evaluate( "si*sin(5)si")); - Assert.assertEquals("-3.309", cm.evaluate( "sisin(5si)si")); - } finally { - cm.setAngleUnits(defaultAngleUnit); - } - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("s", 1d)); - Assert.assertEquals("5", cm.evaluate( "si")); - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("k", 3.5d)); - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("k1", 4d)); - Assert.assertEquals("4", cm.evaluate( "k11")); - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null)); - Assert.assertEquals("11t", cm.evaluate( "t11")); - Assert.assertEquals("11et", cm.evaluate( "t11e")); - Assert.assertEquals("∞", cm.evaluate( "∞")); - Assert.assertEquals("∞", cm.evaluate( "Infinity")); - Assert.assertEquals("11∞t", cm.evaluate( "t11∞")); - Assert.assertEquals("-t+t^3", cm.evaluate( "t(t-1)(t+1)")); - - Assert.assertEquals("100", cm.evaluate( "0.1E3")); - Assert.assertEquals("3.957", cm.evaluate( "ln(8)lg(8)+ln(8)")); - - Assert.assertEquals("0.933", cm.evaluate( "0x:E/0x:F")); - - try { - cm.setNumeralBase(NumeralBase.hex); - Assert.assertEquals("E/F", cm.evaluate( "0x:E/0x:F")); - Assert.assertEquals("E/F", cm.simplify( "0x:E/0x:F")); - Assert.assertEquals("E/F", cm.evaluate( "E/F")); - Assert.assertEquals("E/F", cm.simplify( "E/F")); - } finally { - cm.setNumeralBase(NumeralBase.dec); - } - - Assert.assertEquals("0", cm.evaluate( "((((((0))))))")); - Assert.assertEquals("0", cm.evaluate( "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))")); - - - /* Assert.assertEquals("0.524", cm.evaluate( "30°").getResult()); - Assert.assertEquals("0.524", cm.evaluate( "(10+20)°").getResult()); - Assert.assertEquals("1.047", cm.evaluate( "(10+20)°*2").getResult()); - try { - Assert.assertEquals("0.278", cm.evaluate( "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( "2!").getResult()); - } finally { - cm.setTimeout(3000); - }*/ - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null)); - Assert.assertEquals("2t", cm.simplify( "∂(t^2,t)")); - Assert.assertEquals("2t", cm.evaluate( "∂(t^2,t)")); - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", "2")); - Assert.assertEquals("2t", cm.simplify( "∂(t^2,t)")); - Assert.assertEquals("4", cm.evaluate( "∂(t^2,t)")); - - Assert.assertEquals("-x+x*ln(x)", cm.simplify("∫(ln(x), x)")); - Assert.assertEquals("-(x-x*ln(x))/(ln(2)+ln(5))", cm.simplify("∫(log(10, x), x)")); - - Assert.assertEquals("∫((ln(2)+ln(5))/ln(x), x)", cm.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.simplify("∫(log(x, 10), x)")); - } - - @Test - public void testFormatting() throws Exception { - final MathEngine ce = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - Assert.assertEquals("12 345", ce.simplify( "12345")); - - } - - @Test - public void testI() throws ParseException, CalculatorEvalException { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - Assert.assertEquals("-i", cm.evaluate( "i^3")); - 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( sb.toString()); - } catch (Throwable e) { - fail(sb.toString()); - } - } - } - - @Test - public void testEmptyFunction() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - try { - cm.evaluate( "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 (ParseException e) { - } - Assert.assertEquals("0.34+1.382i", cm.evaluate( "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))")); - try { - cm.evaluate( "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 (ParseException e) { - } - - final AngleUnit defaultAngleUnit = cm.getAngleUnits(); - try { - cm.setAngleUnits(AngleUnit.rad); - Assert.assertEquals("0.739", cm.evaluate( "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))))))))))))))))))))))))))))))))))))")); - } finally { - cm.setAngleUnits(defaultAngleUnit); - } - - CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("si", 5d)); - Assert.assertEquals("5", cm.evaluate( "si")); - - try { - cm.evaluate( "sin"); - Assert.fail(); - } catch (ParseException e) { - } - } - - @Test - public void testRounding() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - 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( "1.23456789E7")); - cm.setPrecision(10); - Assert.assertEquals("12'345'678.9", cm.evaluate( "1.23456789E7")); - Assert.assertEquals("123'456'789", cm.evaluate( "1.234567890E8")); - Assert.assertEquals("1'234'567'890.1", cm.evaluate( "1.2345678901E9")); - } 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 MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - Assert.assertEquals("0", cm.evaluate( "eq(0, 1)")); - Assert.assertEquals("1", cm.evaluate( "eq(1, 1)")); - Assert.assertEquals("1", cm.evaluate( "eq(1, 1.0)")); - Assert.assertEquals("0", cm.evaluate( "eq(1, 1.000000000000001)")); - Assert.assertEquals("0", cm.evaluate( "eq(1, 0)")); - - Assert.assertEquals("1", cm.evaluate( "lt(0, 1)")); - Assert.assertEquals("0", cm.evaluate( "lt(1, 1)")); - Assert.assertEquals("0", cm.evaluate( "lt(1, 0)")); - - Assert.assertEquals("0", cm.evaluate( "gt(0, 1)")); - Assert.assertEquals("0", cm.evaluate( "gt(1, 1)")); - Assert.assertEquals("1", cm.evaluate( "gt(1, 0)")); - - Assert.assertEquals("1", cm.evaluate( "ne(0, 1)")); - Assert.assertEquals("0", cm.evaluate( "ne(1, 1)")); - Assert.assertEquals("1", cm.evaluate( "ne(1, 0)")); - - Assert.assertEquals("1", cm.evaluate( "le(0, 1)")); - Assert.assertEquals("1", cm.evaluate( "le(1, 1)")); - Assert.assertEquals("0", cm.evaluate( "le(1, 0)")); - - Assert.assertEquals("0", cm.evaluate( "ge(0, 1)")); - Assert.assertEquals("1", cm.evaluate( "ge(1, 1)")); - Assert.assertEquals("1", cm.evaluate( "ge(1, 0)")); - - Assert.assertEquals("0", cm.evaluate( "ap(0, 1)")); - Assert.assertEquals("1", cm.evaluate( "ap(1, 1)")); - //Assert.assertEquals("1", cm.evaluate( "ap(1, 1.000000000000001)").getResult()); - Assert.assertEquals("0", cm.evaluate( "ap(1, 0)")); - - } - - - @Test - public void testNumeralSystems() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - Assert.assertEquals("11 259 375", cm.evaluate( "0x:ABCDEF")); - Assert.assertEquals("30 606 154.462", cm.evaluate( "0x:ABCDEF*e")); - Assert.assertEquals("30 606 154.462", cm.evaluate( "e*0x:ABCDEF")); - Assert.assertEquals("e", cm.evaluate( "e*0x:ABCDEF/0x:ABCDEF")); - Assert.assertEquals("30 606 154.462", cm.evaluate( "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF")); - Assert.assertEquals("30 606 154.462", cm.evaluate( "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C")); - Assert.assertEquals("1 446 257 064 651.832", cm.evaluate( "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) ")); - Assert.assertEquals("13", cm.evaluate( "0b:1101")); - - try { - cm.evaluate( "0b:π"); - Assert.fail(); - } catch (ParseException e) { - // ok - } - - final NumeralBase defaultNumeralBase = cm.getNumeralBase(); - try{ - cm.setNumeralBase(NumeralBase.bin); - Assert.assertEquals("101", cm.evaluate( "10+11")); - Assert.assertEquals("10/11", cm.evaluate( "10/11")); - - cm.setNumeralBase(NumeralBase.hex); - Assert.assertEquals("63 7B", cm.evaluate( "56CE+CAD")); - Assert.assertEquals("E", cm.evaluate( "E")); - } finally { - cm.setNumeralBase(defaultNumeralBase); - } - } - - @Test - public void testLog() throws Exception { - final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); - - 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( "log(1, 10)")); - Assert.assertEquals("3.322", cm.evaluate( "log(2, 10)")); - Assert.assertEquals("1.431", cm.evaluate( "log(5, 10)")); - Assert.assertEquals("0.96", cm.evaluate( "log(11, 10)")); - Assert.assertEquals("1/(bln(a))", cm.simplify( "∂(log(a, b), b)")); - Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.simplify( "∂(log(a, b), a)")); - - } -} +/* + * 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.MathEngine; +import jscl.NumeralBase; +import jscl.math.Expression; +import jscl.math.Generic; +import jscl.math.function.Constant; +import jscl.math.function.CustomFunction; +import jscl.text.ParseException; +import junit.framework.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.solovyev.android.calculator.AbstractCalculatorTest; +import org.solovyev.android.calculator.CalculatorEvalException; +import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.CalculatorTestUtils; +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 + */ + +@SuppressWarnings("deprecation") +public class AndroidCalculatorEngineTest extends AbstractCalculatorTest { + + @BeforeClass + public static void staticSetUp() throws Exception { + CalculatorTestUtils.staticSetUp(); + CalculatorLocatorImpl.getInstance().getEngine().setPrecision(3); + } + + + @Test + public void testDegrees() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + final AngleUnit defaultAngleUnit = cm.getAngleUnits(); + try { + cm.setAngleUnits(AngleUnit.rad); + cm.setPrecision(3); + CalculatorTestUtils.assertError("°"); + CalculatorTestUtils.assertEval("0.017", "1°"); + CalculatorTestUtils.assertEval("0.349", "20.0°"); + CalculatorTestUtils.assertEval("0.5", "sin(30°)"); + CalculatorTestUtils.assertEval("0.524", "asin(sin(30°))"); + CalculatorTestUtils.assertEval("∂(cos(t), t, t, 1°)", "∂(cos(t),t,t,1°)"); + + CalculatorTestUtils.assertEval("∂(cos(t), t, t, 1°)", "∂(cos(t),t,t,1°)", JsclOperation.simplify); + } finally { + cm.setAngleUnits(defaultAngleUnit); + } + } + +/* @Test + public void testLongExecution() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + try { + cm.evaluate( "3^10^10^10"); + fail(); + } catch (ParseException e) { + if (e.getMessageCode().equals(Messages.msg_3)) { + + } else { + System.out.print(e.getCause().getMessage()); + fail(); + } + } + + try { + cm.evaluate("9999999!"); + fail(); + } catch (ParseException e) { + if (e.getMessageCode().equals(Messages.msg_3)) { + + } else { + System.out.print(e.getCause().getMessage()); + fail(); + } + } + + final long start = System.currentTimeMillis(); + try { + cm.evaluate( "3^10^10^10"); + fail(); + } catch (ParseException e) { + if (e.getMessage().startsWith("Too long calculation")) { + final long end = System.currentTimeMillis(); + Assert.assertTrue(end - start < 1000); + } else { + fail(); + } + } + + }*/ + + @Test + public void testEvaluate() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("cos(t)+10%", "cos(t)+10%", JsclOperation.simplify); + + final Generic expression = cm.simplifyGeneric("cos(t)+10%"); + expression.substitute(new Constant("t"), Expression.valueOf(100d)); + + CalculatorTestUtils.assertEval("it", "it", JsclOperation.simplify); + CalculatorTestUtils.assertEval("10%", "10%", JsclOperation.simplify); + CalculatorTestUtils.assertEval("0", "eq(0, 1)"); + CalculatorTestUtils.assertEval("1", "eq(1, 1)"); + CalculatorTestUtils.assertEval("1", "eq( 1, 1)"); + CalculatorTestUtils.assertEval("1", "eq( 1, 1)", JsclOperation.simplify); + CalculatorTestUtils.assertEval("1", "lg(10)"); + CalculatorTestUtils.assertEval("4", "2+2"); + final AngleUnit defaultAngleUnit = cm.getAngleUnits(); + try { + cm.setAngleUnits(AngleUnit.rad); + CalculatorTestUtils.assertEval("-0.757", "sin(4)"); + CalculatorTestUtils.assertEval("0.524", "asin(0.5)"); + CalculatorTestUtils.assertEval("-0.396", "sin(4)asin(0.5)"); + CalculatorTestUtils.assertEval("-0.56", "sin(4)asin(0.5)√(2)"); + CalculatorTestUtils.assertEval("-0.56", "sin(4)asin(0.5)√(2)"); + } finally { + cm.setAngleUnits(defaultAngleUnit); + } + CalculatorTestUtils.assertEval("7.389", "e^2"); + CalculatorTestUtils.assertEval("7.389", "exp(1)^2"); + CalculatorTestUtils.assertEval("7.389", "exp(2)"); + CalculatorTestUtils.assertEval("2+i", "2*1+√(-1)"); + try { + cm.setAngleUnits(AngleUnit.rad); + CalculatorTestUtils.assertEval("0.921+Πi", "ln(5cosh(38π√(2cos(2))))"); + CalculatorTestUtils.assertEval("-3.41+3.41i", "(5tan(2i)+2i)/(1-i)"); + } finally { + cm.setAngleUnits(defaultAngleUnit); + } + CalculatorTestUtils.assertEval("7.389i", "iexp(2)"); + CalculatorTestUtils.assertEval("2+7.389i", "2+iexp(2)"); + CalculatorTestUtils.assertEval("2+7.389i", "2+√(-1)exp(2)"); + CalculatorTestUtils.assertEval("2-2.5i", "2-2.5i"); + CalculatorTestUtils.assertEval("-2-2.5i", "-2-2.5i"); + CalculatorTestUtils.assertEval("-2+2.5i", "-2+2.5i"); + CalculatorTestUtils.assertEval("-2+2.1i", "-2+2.1i"); + CalculatorTestUtils.assertEval("-0.1-0.2i", "(1-i)/(2+6i)"); + + CalculatorTestUtils.assertEval("24", "4!"); + CalculatorTestUtils.assertEval("24", "(2+2)!"); + CalculatorTestUtils.assertEval("120", "(2+2+1)!"); + CalculatorTestUtils.assertEval("24", "(2.0+2.0)!"); + CalculatorTestUtils.assertEval("24", "4.0!"); + CalculatorTestUtils.assertEval("720", "(3!)!"); + CalculatorTestUtils.assertEval("36", Expression.valueOf("3!^2").numeric().toString()); + CalculatorTestUtils.assertEval("3", Expression.valueOf("cubic(27)").numeric().toString()); + CalculatorTestUtils.assertError("i!"); + + CalculatorTestUtils.assertEval("1", cm.evaluate( "(π/π)!")); + + CalculatorTestUtils.assertError("(-1)i!"); + CalculatorTestUtils.assertEval("24i", "4!i"); + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("si", 5d)); + + try { + cm.setAngleUnits(AngleUnit.rad); + CalculatorTestUtils.assertEval("0.451", "acos(0.8999999999999811)"); + CalculatorTestUtils.assertEval("-0.959", "sin(5)"); + CalculatorTestUtils.assertEval("-4.795", "sin(5)si"); + CalculatorTestUtils.assertEval("-23.973", "sisin(5)si"); + CalculatorTestUtils.assertEval("-23.973", "si*sin(5)si"); + CalculatorTestUtils.assertEval("-3.309", "sisin(5si)si"); + } finally { + cm.setAngleUnits(defaultAngleUnit); + } + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("s", 1d)); + CalculatorTestUtils.assertEval("5", cm.evaluate( "si")); + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("k", 3.5d)); + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("k1", 4d)); + CalculatorTestUtils.assertEval("4", "k11"); + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null)); + CalculatorTestUtils.assertEval("11t", "t11"); + CalculatorTestUtils.assertEval("11et", "t11e"); + CalculatorTestUtils.assertEval("∞", "∞"); + CalculatorTestUtils.assertEval("∞", "Infinity"); + CalculatorTestUtils.assertEval("11∞t", "t11∞"); + CalculatorTestUtils.assertEval("-t+t^3", "t(t-1)(t+1)"); + + CalculatorTestUtils.assertEval("100", "0.1E3"); + CalculatorTestUtils.assertEval("3.957", "ln(8)lg(8)+ln(8)"); + + CalculatorTestUtils.assertEval("0.933", "0x:E/0x:F"); + + try { + cm.setNumeralBase(NumeralBase.hex); + CalculatorTestUtils.assertEval("E/F", "0x:E/0x:F"); + CalculatorTestUtils.assertEval("E/F", cm.simplify( "0x:E/0x:F")); + CalculatorTestUtils.assertEval("E/F", "E/F"); + CalculatorTestUtils.assertEval("E/F", cm.simplify( "E/F")); + } finally { + cm.setNumeralBase(NumeralBase.dec); + } + + CalculatorTestUtils.assertEval("0", "((((((0))))))"); + CalculatorTestUtils.assertEval("0", "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"); + + + /* CalculatorTestUtils.assertEval("0.524", cm.evaluate( "30°").getResult()); + CalculatorTestUtils.assertEval("0.524", cm.evaluate( "(10+20)°").getResult()); + CalculatorTestUtils.assertEval("1.047", cm.evaluate( "(10+20)°*2").getResult()); + try { + CalculatorTestUtils.assertEval("0.278", cm.evaluate( "30°^2").getResult()); + fail(); + } catch (ParseException e) { + if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) { + fail(); + } + }*//* + +*//* try { + cm.setTimeout(5000); + CalculatorTestUtils.assertEval("2", cm.evaluate( "2!").getResult()); + } finally { + cm.setTimeout(3000); + }*/ + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null)); + CalculatorTestUtils.assertEval("2t", "∂(t^2,t)", JsclOperation.simplify); + CalculatorTestUtils.assertEval("2t", "∂(t^2,t)"); + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", "2")); + CalculatorTestUtils.assertEval("2t", "∂(t^2,t)", JsclOperation.simplify); + CalculatorTestUtils.assertEval("4", "∂(t^2,t)"); + + CalculatorTestUtils.assertEval("-x+xln(x)", "∫(ln(x), x)", JsclOperation.simplify); + CalculatorTestUtils.assertEval("-(x-xln(x))/(ln(2)+ln(5))", "∫(log(10, x), x)", JsclOperation.simplify); + + CalculatorTestUtils.assertEval("∫((ln(2)+ln(5))/ln(x), x)", "∫(ln(10)/ln(x), x)", JsclOperation.simplify); + //CalculatorTestUtils.assertEval("∫(ln(10)/ln(x), x)", Expression.valueOf("∫(log(x, 10), x)").expand().toString()); + CalculatorTestUtils.assertEval("∫((ln(2)+ln(5))/ln(x), x)", "∫(log(x, 10), x)"); + CalculatorTestUtils.assertEval("∫((ln(2)+ln(5))/ln(x), x)", "∫(log(x, 10), x)", JsclOperation.simplify); + } + + @Test + public void testFormatting() throws Exception { + final MathEngine ce = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("12 345", ce.simplify( "12345")); + + } + + @Test + public void testI() throws ParseException, CalculatorEvalException { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("-i", cm.evaluate( "i^3")); + 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( sb.toString()); + } catch (Throwable e) { + fail(sb.toString()); + } + } + } + + @Test + public void testEmptyFunction() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + try { + cm.evaluate( "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 (ParseException e) { + } + CalculatorTestUtils.assertEval("0.34+1.382i", "ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(ln(100)))))))))))))))"); + try { + cm.evaluate( "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 (ParseException e) { + } + + final AngleUnit defaultAngleUnit = cm.getAngleUnits(); + try { + cm.setAngleUnits(AngleUnit.rad); + CalculatorTestUtils.assertEval("0.739", cm.evaluate( "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))))))))))))))))))))))))))))))))))))")); + } finally { + cm.setAngleUnits(defaultAngleUnit); + } + + CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("si", 5d)); + CalculatorTestUtils.assertEval("5", cm.evaluate( "si")); + + CalculatorTestUtils.assertError("sin"); + } + + @Test + public void testRounding() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + try { + DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault()); + decimalGroupSymbols.setDecimalSeparator('.'); + decimalGroupSymbols.setGroupingSeparator('\''); + cm.setDecimalGroupSymbols(decimalGroupSymbols); + cm.setPrecision(2); + CalculatorTestUtils.assertEval("12'345'678.9", cm.evaluate( "1.23456789E7")); + cm.setPrecision(10); + CalculatorTestUtils.assertEval("12'345'678.9", cm.evaluate( "1.23456789E7")); + CalculatorTestUtils.assertEval("123'456'789", cm.evaluate( "1.234567890E8")); + CalculatorTestUtils.assertEval("1'234'567'890.1", cm.evaluate( "1.2345678901E9")); + } 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 MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("0", "eq(0, 1)"); + CalculatorTestUtils.assertEval("1", "eq(1, 1)"); + CalculatorTestUtils.assertEval("1", "eq(1, 1.0)"); + CalculatorTestUtils.assertEval("0", "eq(1, 1.000000000000001)"); + CalculatorTestUtils.assertEval("0", "eq(1, 0)"); + + CalculatorTestUtils.assertEval("1", "lt(0, 1)"); + CalculatorTestUtils.assertEval("0", "lt(1, 1)"); + CalculatorTestUtils.assertEval("0", "lt(1, 0)"); + + CalculatorTestUtils.assertEval("0", "gt(0, 1)"); + CalculatorTestUtils.assertEval("0", "gt(1, 1)"); + CalculatorTestUtils.assertEval("1", "gt(1, 0)"); + + CalculatorTestUtils.assertEval("1", "ne(0, 1)"); + CalculatorTestUtils.assertEval("0", "ne(1, 1)"); + CalculatorTestUtils.assertEval("1", "ne(1, 0)"); + + CalculatorTestUtils.assertEval("1", "le(0, 1)"); + CalculatorTestUtils.assertEval("1", "le(1, 1)"); + CalculatorTestUtils.assertEval("0", "le(1, 0)"); + + CalculatorTestUtils.assertEval("0", "ge(0, 1)"); + CalculatorTestUtils.assertEval("1", "ge(1, 1)"); + CalculatorTestUtils.assertEval("1", "ge(1, 0)"); + + CalculatorTestUtils.assertEval("0", "ap(0, 1)"); + CalculatorTestUtils.assertEval("1", "ap(1, 1)"); + CalculatorTestUtils.assertEval("0", "ap(1, 0)"); + + } + + + @Test + public void testNumeralSystems() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("11 259 375", "0x:ABCDEF"); + CalculatorTestUtils.assertEval("30 606 154.462", "0x:ABCDEF*e"); + CalculatorTestUtils.assertEval("30 606 154.462", "e*0x:ABCDEF"); + CalculatorTestUtils.assertEval("e", "e*0x:ABCDEF/0x:ABCDEF"); + CalculatorTestUtils.assertEval("30 606 154.462", "0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF"); + CalculatorTestUtils.assertEval("30 606 154.462", "c+0x:ABCDEF*e*0x:ABCDEF/0x:ABCDEF-c+0x:C-0x:C"); + CalculatorTestUtils.assertEval("1 446 257 064 651.832", "28*28 * sin(28) - 0b:1101 + √(28) + exp ( 28) "); + CalculatorTestUtils.assertEval("13", "0b:1101"); + + CalculatorTestUtils.assertError("0b:π"); + + final NumeralBase defaultNumeralBase = cm.getNumeralBase(); + try{ + cm.setNumeralBase(NumeralBase.bin); + CalculatorTestUtils.assertEval("101", "10+11"); + CalculatorTestUtils.assertEval("10/11", "10/11"); + + cm.setNumeralBase(NumeralBase.hex); + CalculatorTestUtils.assertEval("63 7B", "56CE+CAD"); + CalculatorTestUtils.assertEval("E", "E"); + } finally { + cm.setNumeralBase(defaultNumeralBase); + } + } + + @Test + public void testLog() throws Exception { + final MathEngine cm = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0(); + + CalculatorTestUtils.assertEval("∞", Expression.valueOf("1/0").numeric().toString()); + CalculatorTestUtils.assertEval("∞", Expression.valueOf("ln(10)/ln(1)").numeric().toString()); + + // logarithm + CalculatorTestUtils.assertEval("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent()); + CalculatorTestUtils.assertEval("∞", "log(1, 10)"); + CalculatorTestUtils.assertEval("3.322", "log(2, 10)"); + CalculatorTestUtils.assertEval("1.431", "log(5, 10)"); + CalculatorTestUtils.assertEval("0.96", "log(11, 10)"); + CalculatorTestUtils.assertEval("1/(bln(a))", "∂(log(a, b), b)", JsclOperation.simplify); + CalculatorTestUtils.assertEval("-ln(b)/(aln(a)^2)", "∂(log(a, b), a)", JsclOperation.simplify); + + } +} diff --git a/calculatorpp/proguard.cfg b/calculatorpp/proguard.cfg index fcaec6a6..4f8be4e0 100644 --- a/calculatorpp/proguard.cfg +++ b/calculatorpp/proguard.cfg @@ -1,56 +1,105 @@ --target 1.6 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --repackageclasses '' --allowaccessmodification --optimizations !code/simplification/arithmetic --keepattributes *Annotation* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider - --keep public class * extends android.view.View { - public (android.content.Context); - public (android.content.Context, android.util.AttributeSet); - public (android.content.Context, android.util.AttributeSet, int); - public void set*(...); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.content.Context { - public void *(android.view.View); - public void *(android.view.MenuItem); -} - --keepclassmembers class * implements android.os.Parcelable { - static android.os.Parcelable$Creator CREATOR; -} - --keepclassmembers class **.R$* { - public static ; -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --dontwarn javax.xml.stream.** --dontwarn com.bea.xml.stream.** --dontwarn sun.misc.Unsafe --dontwarn android.annotation.TargetApi - --keep class org.simpleframework.xml.** { *; } --keep class com.actionbarsherlock.** { *; } --keep class * implements org.solovyev.android.calculator.model.MathPersistenceEntity +-target 1.6 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-repackageclasses '' +-allowaccessmodification +-optimizations !code/simplification/arithmetic +-keepattributes *Annotation* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider + +-keep public class * extends android.view.View { + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); + public void set*(...); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers class * extends android.content.Context { + public void *(android.view.View); + public void *(android.view.MenuItem); +} + +-keepclassmembers class * implements android.os.Parcelable { + static android.os.Parcelable$Creator CREATOR; +} + +-keepclassmembers class **.R$* { + public static ; +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep @org.simpleframework.xml.Root public class * { + *; +} + +-dontwarn javax.xml.stream.** +-dontwarn com.bea.xml.stream.** +-dontwarn sun.misc.Unsafe +-dontwarn android.annotation.TargetApi +-dontwarn org.solovyev.common.math.visualisation.** +-dontwarn org.solovyev.common.math.graph.** +-dontwarn org.solovyev.common.math.algorithms.** +-dontwarn org.solovyev.common.drawing.** +-dontwarn org.joda.** +-dontwarn jscl.mathml.** +-dontwarn com.google.common.collect.MinMaxPriorityQueue + +-keep class org.simpleframework.xml.** { *; } +-keep class com.actionbarsherlock.** { *; } +-keep class * implements org.solovyev.android.calculator.model.MathPersistenceEntity + +# +#********************************************************************* +# +# ACRA +# +#********************************************************************* +# + +# we need line numbers in our stack traces otherwise they are pretty useless +-renamesourcefileattribute SourceFile +-keepattributes SourceFile,LineNumberTable + +# ACRA needs "annotations" so add this... +-keepattributes *Annotation* + +# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'. +# Note: if you are removing log messages elsewhere in this file then this isn't necessary +-keep class org.acra.ACRA { + *; +} + +# keep this around for some enums that ACRA needs +-keep class org.acra.ReportingInteractionMode { + *; +} + +# keep this otherwise it is removed by ProGuard +-keep public class org.acra.ErrorReporter +{ +public void addCustomData(java.lang.String,java.lang.String); +} + +# keep this otherwise it is removed by ProGuard +-keep public class org.acra.ErrorReporter +{ +public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable); +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AndroidMathEntityDao.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AndroidMathEntityDao.java index fc17153c..66c098f9 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AndroidMathEntityDao.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/model/AndroidMathEntityDao.java @@ -1,95 +1,99 @@ -package org.solovyev.android.calculator.model; - -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.preference.PreferenceManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.simpleframework.xml.Serializer; -import org.simpleframework.xml.core.Persister; -import org.solovyev.android.calculator.MathEntityDao; -import org.solovyev.android.calculator.MathEntityPersistenceContainer; -import org.solovyev.android.calculator.MathPersistenceEntity; -import org.solovyev.android.calculator.R; - -import java.io.StringWriter; - -/** - * User: serso - * Date: 10/7/12 - * Time: 6:46 PM - */ -public class AndroidMathEntityDao implements MathEntityDao { - - @Nullable - private final Integer preferenceStringId; - - @NotNull - private final Context context; - - @Nullable - private final Class> persistenceContainerClass; - - public AndroidMathEntityDao(@Nullable Integer preferenceStringId, - @NotNull Application application, - @Nullable Class> persistenceContainerClass) { - this.preferenceStringId = preferenceStringId; - this.context = application; - this.persistenceContainerClass = persistenceContainerClass; - } - - @Override - public void save(@NotNull MathEntityPersistenceContainer container) { - if (preferenceStringId != null) { - final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - final SharedPreferences.Editor editor = settings.edit(); - - final StringWriter sw = new StringWriter(); - final Serializer serializer = new Persister(); - try { - serializer.write(container, sw); - } catch (Exception e) { - throw new RuntimeException(e); - } - - editor.putString(context.getString(preferenceStringId), sw.toString()); - - editor.commit(); - } - } - - @Nullable - @Override - public MathEntityPersistenceContainer load() { - if (persistenceContainerClass != null && preferenceStringId != null) { - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - if (preferences != null) { - final String value = preferences.getString(context.getString(preferenceStringId), null); - if (value != null) { - final Serializer serializer = new Persister(); - try { - return serializer.read(persistenceContainerClass, value); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } - - return null; - } - - @Nullable - public String getDescription(@NotNull String descriptionId) { - final Resources resources = context.getResources(); - final int stringId = resources.getIdentifier(descriptionId, "string", R.class.getPackage().getName()); - try { - return resources.getString(stringId); - } catch (Resources.NotFoundException e) { - return null; - } - } -} +package org.solovyev.android.calculator.model; + +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.preference.PreferenceManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.simpleframework.xml.Serializer; +import org.simpleframework.xml.core.Persister; +import org.solovyev.android.calculator.CalculatorApplication; +import org.solovyev.android.calculator.MathEntityDao; +import org.solovyev.android.calculator.MathEntityPersistenceContainer; +import org.solovyev.android.calculator.MathPersistenceEntity; + +import java.io.StringWriter; + +/** + * User: serso + * Date: 10/7/12 + * Time: 6:46 PM + */ +public class AndroidMathEntityDao implements MathEntityDao { + + @NotNull + private static final String TAG = AndroidMathEntityDao.class.getSimpleName(); + + @Nullable + private final Integer preferenceStringId; + + @NotNull + private final Context context; + + @Nullable + private final Class> persistenceContainerClass; + + public AndroidMathEntityDao(@Nullable Integer preferenceStringId, + @NotNull Application application, + @Nullable Class> persistenceContainerClass) { + this.preferenceStringId = preferenceStringId; + this.context = application; + this.persistenceContainerClass = persistenceContainerClass; + } + + @Override + public void save(@NotNull MathEntityPersistenceContainer container) { + if (preferenceStringId != null) { + final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + final SharedPreferences.Editor editor = settings.edit(); + + final StringWriter sw = new StringWriter(); + final Serializer serializer = new Persister(); + try { + serializer.write(container, sw); + } catch (Exception e) { + throw new RuntimeException(e); + } + + editor.putString(context.getString(preferenceStringId), sw.toString()); + + editor.commit(); + } + } + + @Nullable + @Override + public MathEntityPersistenceContainer load() { + if (persistenceContainerClass != null && preferenceStringId != null) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + if (preferences != null) { + final String value = preferences.getString(context.getString(preferenceStringId), null); + if (value != null) { + final Serializer serializer = new Persister(); + try { + return serializer.read(persistenceContainerClass, value); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } + + return null; + } + + @Nullable + public String getDescription(@NotNull String descriptionId) { + final Resources resources = context.getResources(); + + final int stringId = resources.getIdentifier(descriptionId, "string", CalculatorApplication.class.getPackage().getName()); + try { + return resources.getString(stringId); + } catch (Resources.NotFoundException e) { + return null; + } + } +} diff --git a/pom.xml b/pom.xml index 529242c7..d4fe4fdf 100644 --- a/pom.xml +++ b/pom.xml @@ -1,275 +1,280 @@ - - - - 4.0.0 - - org.solovyev.android - calculatorpp-parent - pom - 1.3.2 - Calculator++ - - - calculatorpp - calculatorpp-test - calculatorpp-core - - - - UTF-8 - - - - - - - org.solovyev - common-core - 1.0.0 - - - - org.solovyev - common-text - 1.0.1 - - - - org.solovyev.android - android-common-core - apklib - 1.0.0 - - - - org.solovyev.android - android-common-ads - apklib - 1.0.0 - - - - org.solovyev.android - android-common-view - apklib - 1.0.0 - - - - org.solovyev.android - android-common-preferences - apklib - 1.0.0 - - - - org.solovyev.android - android-common-menu - apklib - 1.0.0 - - - - org.solovyev.android - android-common-sherlock - 1.0.0 - apklib - - - - com.actionbarsherlock - library - 4.1.0 - apklib - - - - org.solovyev - jscl - 0.0.3 - - - xercesImpl - xerces - - - - - - org.solovyev.android - android-common-other - apklib - 1.0.0 - - - - junit - junit - 4.8.2 - - - - com.intellij - annotations - 7.0.3 - - - - com.google.android - android - 4.0.1.2 - provided - - - - com.google.android - support-v4 - r7 - - - - com.google.android - android-test - 2.3.1 - - - - com.google.guava - guava - 11.0.2 - - - - org.simpleframework - simple-xml - 2.6.1 - - - stax-api - stax - - - xpp3 - xpp3 - - - - - - - - - - - - - com.electriccloud - javac2-maven-plugin - 1.0.1 - - - @NotNull Instrumentation - - instrument - - - compile - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.12.3 - - perTest - - - - - - - - - - org.apache.maven.plugins - maven-jarsigner-plugin - 1.2 - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - 3.1.1 - - - - ${project.basedir}/src/main/java - - - - 15 - - - - 23 - 10000 - - - - - true - - - true - - - - - - - com.pyx4me - proguard-maven-plugin - 2.0.4 - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.5 - - - - - - - - - - - - standard - - - - - release - - - - performRelease - true - - - - - - - + + + + 4.0.0 + + org.solovyev.android + calculatorpp-parent + pom + 1.3.2 + Calculator++ + + + calculatorpp + calculatorpp-test + calculatorpp-core + + + + UTF-8 + + + + + + + org.solovyev + common-core + 1.0.0 + + + + org.solovyev + common-text + 1.0.1 + + + + org.solovyev.android + android-common-core + apklib + 1.0.0 + + + + org.solovyev.android + android-common-ads + apklib + 1.0.0 + + + + org.solovyev.android + android-common-view + apklib + 1.0.0 + + + + org.solovyev.android + android-common-preferences + apklib + 1.0.0 + + + + org.solovyev.android + android-common-menu + apklib + 1.0.0 + + + + org.solovyev.android + android-common-sherlock + 1.0.0 + apklib + + + + com.actionbarsherlock + library + 4.1.0 + apklib + + + + org.solovyev + jscl + 0.0.3 + + + xercesImpl + xerces + + + + jgraphx + jgraphx + + + + + + org.solovyev.android + android-common-other + apklib + 1.0.0 + + + + junit + junit + 4.8.2 + + + + com.intellij + annotations + 7.0.3 + + + + com.google.android + android + 4.0.1.2 + provided + + + + com.google.android + support-v4 + r7 + + + + com.google.android + android-test + 2.3.1 + + + + com.google.guava + guava + 11.0.2 + + + + org.simpleframework + simple-xml + 2.6.1 + + + stax-api + stax + + + xpp3 + xpp3 + + + + + + + + + + + + + com.electriccloud + javac2-maven-plugin + 1.0.1 + + + @NotNull Instrumentation + + instrument + + + compile + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.3 + + perTest + + + + + + + + + + org.apache.maven.plugins + maven-jarsigner-plugin + 1.2 + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + 3.1.1 + + + + ${project.basedir}/src/main/java + + + + 15 + + + + 23 + 10000 + + + + + true + + + true + + + + + + + com.pyx4me + proguard-maven-plugin + 2.0.4 + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.5 + + + + + + + + + + + + standard + + + + + release + + + + performRelease + true + + + + + + + \ No newline at end of file