Variables refactor

This commit is contained in:
serso 2016-01-28 15:19:18 +01:00
parent 2448f1b387
commit cb2047d05e
41 changed files with 673 additions and 737 deletions

View File

@ -27,33 +27,43 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Handler;
import android.support.annotation.NonNull;
import com.squareup.otto.Bus;
import org.json.JSONArray;
import org.json.JSONException;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.model.EntityDao;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.android.io.FileSaver;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends PersistedEntity> implements EntitiesRegistry<T> {
public abstract class BaseEntitiesRegistry<T extends MathEntity> implements EntitiesRegistry<T> {
@Nullable
protected final EntityDao<P> entityDao;
@Nonnull
protected final Object lock = this;
@Nonnull
private final MathRegistry<T> mathRegistry;
@Nonnull
private final String prefix;
@NonNull
private final WriteTask writeTask = new WriteTask();
@Inject
Handler handler;
@Inject
@ -64,16 +74,17 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
Bus bus;
@Inject
ErrorReporter errorReporter;
@Inject
@Named(AppModule.THREAD_BACKGROUND)
Executor backgroundThread;
// synchronized on lock
private boolean initialized;
protected BaseEntitiesRegistry(@Nonnull MathRegistry<T> mathRegistry,
@Nonnull String prefix,
@Nullable EntityDao<P> entityDao) {
@Nonnull String prefix) {
this.mathRegistry = mathRegistry;
this.prefix = prefix;
this.entityDao = entityDao;
}
@ -96,6 +107,10 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
return getDescription(App.getApplication(), stringName);
}
@Override
public void init() {
setInitialized();
}
@Nullable
public String getDescription(@Nonnull Context context, @Nonnull String descriptionId) {
@ -109,44 +124,18 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
}
}
public synchronized void init() {
Check.isNotMainThread();
if (entityDao == null) {
return;
@NonNull
protected final <E> List<E> loadEntities(@NonNull Json.Creator<E> creator) {
final File file = getEntitiesFile();
if (file == null) {
return Collections.emptyList();
}
final PersistedEntitiesContainer<P> persistenceContainer = entityDao.load();
final List<P> notCreatedEntities = new ArrayList<P>();
if (persistenceContainer != null) {
for (P entity : persistenceContainer.getEntities()) {
if (!contains(entity.getName())) {
try {
final JBuilder<? extends T> builder = createBuilder(entity);
add(builder);
} catch (RuntimeException e) {
Locator.getInstance().getErrorReporter().onException(e);
notCreatedEntities.add(entity);
return Json.load(file, creator);
} catch (IOException | JSONException e) {
errorReporter.onException(e);
}
}
}
}
try {
if (!notCreatedEntities.isEmpty()) {
final StringBuilder errorMessage = new StringBuilder(notCreatedEntities.size() * 100);
for (P notCreatedEntity : notCreatedEntities) {
errorMessage.append(notCreatedEntity).append("\n\n");
}
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_message_dialog, MessageDialogData.newInstance(CalculatorMessages.newErrorMessage(CalculatorMessages.msg_007, errorMessage.toString()), null));
}
} catch (RuntimeException e) {
// just in case
Locator.getInstance().getErrorReporter().onException(e);
}
setInitialized();
return Collections.emptyList();
}
protected final void setInitialized() {
@ -162,33 +151,11 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
}
}
@Nonnull
protected abstract JBuilder<? extends T> createBuilder(@Nonnull P entity);
@Override
public synchronized void save() {
if (entityDao == null) {
return;
public void save() {
handler.removeCallbacks(writeTask);
handler.postDelayed(writeTask, 500);
}
final PersistedEntitiesContainer<P> container = createPersistenceContainer();
for (T entity : this.getEntities()) {
if (!entity.isSystem()) {
final P persistenceEntity = transform(entity);
if (persistenceEntity != null) {
container.getEntities().add(persistenceEntity);
}
}
}
entityDao.save(container);
}
@Nullable
protected abstract P transform(@Nonnull T entity);
@Nonnull
protected abstract PersistedEntitiesContainer<P> createPersistenceContainer();
@Nonnull
@Override
@ -203,8 +170,12 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
}
@Override
public T add(@Nonnull JBuilder<? extends T> JBuilder) {
return mathRegistry.add(JBuilder);
public T add(@Nonnull JBuilder<? extends T> builder) {
final T entity = mathRegistry.add(builder);
if (!entity.isSystem() && isInitialized()) {
save();
}
return entity;
}
@Nullable
@ -220,6 +191,7 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
@Override
public void remove(@Nonnull T var) {
mathRegistry.remove(var);
save();
}
@Nonnull
@ -242,4 +214,43 @@ public abstract class BaseEntitiesRegistry<T extends MathEntity, P extends Persi
public T getById(@Nonnull Integer id) {
return mathRegistry.getById(id);
}
@Nullable
protected abstract Jsonable toJsonable(@NonNull T entity);
@Nullable
protected abstract File getEntitiesFile();
private class WriteTask implements Runnable {
@Override
public void run() {
Check.isMainThread();
final File file = getEntitiesFile();
if (file == null) {
return;
}
final List<Jsonable> entities = new ArrayList<>();
for (T entity : getEntities()) {
if (entity.isSystem()) {
continue;
}
final Jsonable jsonable = toJsonable(entity);
if (jsonable != null) {
entities.add(jsonable);
}
}
backgroundThread.execute(new Runnable() {
@Override
public void run() {
final JSONArray array = Json.toJson(entities);
try {
FileSaver.save(file, array.toString());
} catch (IOException e) {
errorReporter.onException(e);
}
}
});
}
}
}

View File

@ -52,7 +52,7 @@ public enum CalculatorFragmentType {
//keyboard(CalculatorHistoryFragment.class, "history", R.layout.fragment_history, R.string.c_history),
history(RecentHistoryFragment.class, R.layout.fragment_history, R.string.cpp_history_tab_recent),
saved_history(SavedHistoryFragment.class, R.layout.fragment_history, R.string.cpp_history_tab_saved),
variables(VariablesFragment.class, R.layout.vars_fragment, R.string.c_vars),
variables(VariablesFragment.class, R.layout.fragment_entities, R.string.c_vars),
functions(FunctionsFragment.class, R.layout.fragment_entities, R.string.c_functions),
operators(OperatorsFragment.class, R.layout.fragment_entities, R.string.c_operators),
plotter(CalculatorPlotFragment.class, R.layout.cpp_plotter_fragment, R.string.c_graph),

View File

@ -22,21 +22,16 @@
package org.solovyev.android.calculator;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import jscl.AbstractJsclArithmeticException;
import jscl.MathEngine;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.OldVar;
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
import org.solovyev.android.calculator.variables.CppVariable;
import org.solovyev.common.msg.ListMessageRegistry;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageRegistry;
@ -45,14 +40,24 @@ import org.solovyev.common.text.Strings;
import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AbstractJsclArithmeticException;
import jscl.MathEngine;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
public class CalculatorImpl implements Calculator, CalculatorEventListener {
// one minute
@ -472,15 +477,19 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
if (TextUtils.isEmpty(text)) {
return;
}
updateAnsVariable(text);
}
private void updateAnsVariable(@NonNull String value) {
final EntitiesRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVariablesRegistry();
final IConstant ansVar = varsRegistry.get(VariablesRegistry.ANS);
final IConstant variable = varsRegistry.get(VariablesRegistry.ANS);
final OldVar.Builder builder = ansVar != null ? new OldVar.Builder(ansVar) : new OldVar.Builder();
builder.setName(VariablesRegistry.ANS);
builder.setValue(text);
builder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
final CppVariable.Builder b = variable != null ? CppVariable.builder(variable) : CppVariable.builder(VariablesRegistry.ANS);
b.withValue(value);
b.withSystem(true);
b.withDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
VariablesRegistry.saveVariable(varsRegistry, builder, ansVar, this, false);
VariablesRegistry.add(varsRegistry, b.build().toJsclBuilder(), variable, this);
}
@Subscribe

View File

@ -1,16 +0,0 @@
package org.solovyev.android.calculator;
import android.support.annotation.StringRes;
import javax.annotation.Nonnull;
public interface Category {
int ordinal();
@Nonnull
String name();
@StringRes
int title();
}

View File

@ -22,6 +22,7 @@
package org.solovyev.android.calculator;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.math.MathRegistry;

View File

@ -24,64 +24,55 @@ package org.solovyev.android.calculator;
import android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.entities.Entities;
import org.solovyev.android.calculator.function.CppFunction;
import org.solovyev.android.calculator.function.FunctionCategory;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.calculator.model.OldFunction;
import org.solovyev.android.calculator.model.OldFunctions;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.android.calculator.function.OldFunctions;
import org.solovyev.android.io.FileSaver;
import org.solovyev.common.JBuilder;
import org.solovyev.common.text.Strings;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import jscl.JsclMathEngine;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
import static android.text.TextUtils.isEmpty;
@Singleton
public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunction> {
public class FunctionsRegistry extends BaseEntitiesRegistry<Function> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<>();
@Nonnull
private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
static {
substitutes.put("", "sqrt");
}
@NonNull
private final WriteTask writeTask = new WriteTask();
@Inject
@Named(AppModule.THREAD_BACKGROUND)
Executor backgroundThread;
@Inject
Calculator calculator;
@Inject
public FunctionsRegistry(@Nonnull JsclMathEngine mathEngine) {
super(mathEngine.getFunctionsRegistry(), FUNCTION_DESCRIPTION_PREFIX, null);
super(mathEngine.getFunctionsRegistry(), "c_fun_description_");
}
public void add(@NonNull JBuilder<? extends Function> builder, @Nullable Function oldFunction) {
@ -106,8 +97,8 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
addSafely(new CustomFunction.Builder(true, "re", Collections.singletonList("x"), "(x+conjugate(x))/2"));
addSafely(new CustomFunction.Builder(true, "im", Collections.singletonList("x"), "(x-conjugate(x))/(2*i)"));
for (CppFunction function : loadFunctions()) {
addSafely(function.toCustomFunctionBuilder());
for (CppFunction function : loadEntities(CppFunction.JSON_CREATOR)) {
addSafely(function.toJsclBuilder());
}
} finally {
setInitialized();
@ -118,26 +109,15 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
public void remove(@Nonnull Function function) {
super.remove(function);
bus.post(new RemovedEvent(function));
save();
}
@Nullable
@Override
public Function add(@Nonnull JBuilder<? extends Function> builder) {
final Function function = super.add(builder);
if (isInitialized()) {
save();
protected Jsonable toJsonable(@NonNull Function function) {
if (function instanceof IFunction) {
return CppFunction.builder((IFunction) function).build();
}
return function;
}
@NonNull
private List<CppFunction> loadFunctions() {
try {
return Json.load(getFunctionsFile(), CppFunction.JSON_CREATOR);
} catch (IOException | JSONException e) {
errorReporter.onException(e);
}
return Collections.emptyList();
return null;
}
private void migrateOldFunctions() {
@ -151,7 +131,7 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
if (oldFunctions != null) {
List<CppFunction> functions = OldFunctions.toCppFunctions(oldFunctions);
// todo serso: fix multiplication sign issue
FileSaver.save(getFunctionsFile(), Json.toJson(functions).toString());
FileSaver.save(getEntitiesFile(), Json.toJson(functions).toString());
}
preferences.edit().remove(OldFunctions.PREFS_KEY).apply();
} catch (Exception e) {
@ -160,13 +140,8 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
}
@Override
public void save() {
handler.removeCallbacks(writeTask);
handler.postDelayed(writeTask, 500);
}
@NonNull
private File getFunctionsFile() {
protected File getEntitiesFile() {
return new File(application.getFilesDir(), "functions.json");
}
@ -178,13 +153,7 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
@Override
public Category getCategory(@Nonnull Function function) {
for (FunctionCategory category : FunctionCategory.values()) {
if (category.isInCategory(function)) {
return category;
}
}
return null;
return Entities.getCategory(function, FunctionCategory.values());
}
@Nullable
@ -204,55 +173,6 @@ public class FunctionsRegistry extends BaseEntitiesRegistry<Function, OldFunctio
}
@Nonnull
@Override
protected JBuilder<? extends Function> createBuilder(@Nonnull OldFunction function) {
throw new UnsupportedOperationException();
}
@Override
protected OldFunction transform(@Nonnull Function function) {
if (function instanceof CustomFunction) {
return OldFunction.fromIFunction((CustomFunction) function);
} else {
return null;
}
}
@Nonnull
@Override
protected PersistedEntitiesContainer<OldFunction> createPersistenceContainer() {
return new OldFunctions();
}
private class WriteTask implements Runnable {
@Override
public void run() {
Check.isMainThread();
final List<CppFunction> functions = new ArrayList<>();
for (Function function : getEntities()) {
if (function.isSystem()) {
continue;
}
if (function instanceof CustomFunction) {
functions.add(CppFunction.builder((CustomFunction) function).build());
}
}
backgroundThread.execute(new Runnable() {
@Override
public void run() {
final JSONArray array = Json.toJson(functions);
try {
FileSaver.save(getFunctionsFile(), array.toString());
} catch (IOException e) {
errorReporter.onException(e);
}
}
});
}
}
public static final class RemovedEvent {
@NonNull
public final Function function;

View File

@ -22,20 +22,28 @@
package org.solovyev.android.calculator;
import jscl.math.operator.Operator;
import org.solovyev.common.JBuilder;
import android.support.annotation.NonNull;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.entities.Entities;
import org.solovyev.android.calculator.function.FunctionCategory;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.android.calculator.operators.OperatorCategory;
import org.solovyev.common.math.MathRegistry;
import javax.annotation.Nonnull;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class OperatorsRegistry extends BaseEntitiesRegistry<Operator, PersistedEntity> {
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.operator.Operator;
public class OperatorsRegistry extends BaseEntitiesRegistry<Operator> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final String OPERATOR_DESCRIPTION_PREFIX = "c_op_description_";
static {
substitutes.put("Σ", "sum");
@ -47,7 +55,7 @@ public class OperatorsRegistry extends BaseEntitiesRegistry<Operator, PersistedE
}
public OperatorsRegistry(@Nonnull MathRegistry<Operator> functionsRegistry) {
super(functionsRegistry, OPERATOR_DESCRIPTION_PREFIX, null);
super(functionsRegistry, "c_op_description_");
}
@Nonnull
@ -56,30 +64,20 @@ public class OperatorsRegistry extends BaseEntitiesRegistry<Operator, PersistedE
return substitutes;
}
@Nullable
@Override
public Category getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category;
}
}
protected Jsonable toJsonable(@NonNull Operator entity) {
return null;
}
@Nonnull
@Nullable
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull PersistedEntity entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
protected File getEntitiesFile() {
return null;
}
@Override
protected PersistedEntity transform(@Nonnull Operator entity) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Nonnull
@Override
protected PersistedEntitiesContainer<PersistedEntity> createPersistenceContainer() {
return null; //To change body of implemented methods use File | Settings | File Templates.
public Category getCategory(@Nonnull Operator operator) {
return Entities.getCategory(operator, OperatorCategory.values());
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import java.util.List;
public interface PersistedEntitiesContainer<T extends PersistedEntity> {
List<T> getEntities();
}

View File

@ -22,20 +22,27 @@
package org.solovyev.android.calculator;
import jscl.math.operator.Operator;
import org.solovyev.common.JBuilder;
import android.support.annotation.NonNull;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.entities.Entities;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.android.calculator.operators.OperatorCategory;
import org.solovyev.common.math.MathRegistry;
import javax.annotation.Nonnull;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class PostfixFunctionsRegistry extends BaseEntitiesRegistry<Operator, PersistedEntity> {
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.operator.Operator;
public class PostfixFunctionsRegistry extends BaseEntitiesRegistry<Operator> {
@Nonnull
private static final Map<String, String> substitutes = new HashMap<String, String>();
@Nonnull
private static final String POSTFIX_FUNCTION_DESCRIPTION_PREFIX = "c_pf_description_";
static {
substitutes.put("%", "percent");
@ -45,7 +52,7 @@ public class PostfixFunctionsRegistry extends BaseEntitiesRegistry<Operator, Per
}
public PostfixFunctionsRegistry(@Nonnull MathRegistry<Operator> functionsRegistry) {
super(functionsRegistry, POSTFIX_FUNCTION_DESCRIPTION_PREFIX, null);
super(functionsRegistry, "c_pf_description_");
}
@Nonnull
@ -54,30 +61,20 @@ public class PostfixFunctionsRegistry extends BaseEntitiesRegistry<Operator, Per
return substitutes;
}
@Nullable
@Override
protected Jsonable toJsonable(@NonNull Operator entity) {
return null;
}
@Nullable
@Override
protected File getEntitiesFile() {
return null;
}
@Override
public Category getCategory(@Nonnull Operator operator) {
for (OperatorCategory category : OperatorCategory.values()) {
if (category.isInCategory(operator)) {
return category;
}
}
return null;
}
@Nonnull
@Override
protected JBuilder<? extends Operator> createBuilder(@Nonnull PersistedEntity entity) {
throw new UnsupportedOperationException();
}
@Override
protected PersistedEntity transform(@Nonnull Operator entity) {
return null;
}
@Nonnull
@Override
protected PersistedEntitiesContainer<PersistedEntity> createPersistenceContainer() {
throw new UnsupportedOperationException();
return Entities.getCategory(operator, OperatorCategory.values());
}
}

View File

@ -24,15 +24,18 @@ package org.solovyev.android.calculator;
import android.support.annotation.NonNull;
import com.google.common.base.Strings;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.entities.Entities;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.calculator.model.MathEntityBuilder;
import org.solovyev.android.calculator.model.OldFunctions;
import org.solovyev.android.calculator.model.OldVar;
import org.solovyev.android.calculator.model.OldVars;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.android.calculator.variables.CppVariable;
import org.solovyev.android.calculator.variables.OldVars;
import org.solovyev.android.calculator.variables.VariablesCategory;
import org.solovyev.android.io.FileSaver;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
@ -50,10 +53,8 @@ import javax.inject.Singleton;
import jscl.JsclMathEngine;
import jscl.math.function.IConstant;
import static android.text.TextUtils.isEmpty;
@Singleton
public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
public class VariablesRegistry extends BaseEntitiesRegistry<IConstant> {
@Nonnull
public static final String ANS = "ans";
@ -71,19 +72,15 @@ public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
@Inject
public VariablesRegistry(@Nonnull JsclMathEngine mathEngine) {
super(mathEngine.getConstantsRegistry(), "c_var_description_", null);
super(mathEngine.getConstantsRegistry(), "c_var_description_");
}
public static <T extends MathEntity> void saveVariable(@Nonnull EntitiesRegistry<T> registry,
@Nonnull MathEntityBuilder<? extends T> builder,
public static <T extends MathEntity> void add(@Nonnull EntitiesRegistry<T> registry,
@Nonnull JBuilder<? extends T> builder,
@Nullable T editedInstance,
@Nonnull Object source, boolean save) {
@Nonnull Object source) {
final T addedVar = registry.add(builder);
if (save) {
registry.save();
}
if (editedInstance == null) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.constant_added, addedVar, source);
} else {
@ -101,12 +98,16 @@ public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
Check.isNotMainThread();
try {
//migrateOldVariables();
migrateOldVariables();
addSafely("x");
addSafely("y");
addSafely("t");
addSafely("j");
for (CppVariable variable : loadEntities(CppVariable.JSON_CREATOR)) {
addSafely(variable.toJsclBuilder());
}
} finally {
setInitialized();
}
@ -114,7 +115,7 @@ public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
private void migrateOldVariables() {
final String xml = preferences.getString(OldVars.PREFS_KEY, null);
if (isEmpty(xml)) {
if (Strings.isNullOrEmpty(xml)) {
return;
}
try {
@ -122,44 +123,29 @@ public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
final OldVars oldVariables = serializer.read(OldVars.class, xml);
if (oldVariables != null) {
List<CppVariable> variables = OldVars.toCppVariables(oldVariables);
FileSaver.save(getVariablesFile(), Json.toJson(variables).toString());
FileSaver.save(getEntitiesFile(), Json.toJson(variables).toString());
}
preferences.edit().remove(OldFunctions.PREFS_KEY).apply();
preferences.edit().remove(OldVars.PREFS_KEY).apply();
} catch (Exception e) {
errorReporter.onException(e);
}
}
@Override
@NonNull
private File getVariablesFile() {
protected File getEntitiesFile() {
return new File(application.getFilesDir(), "variables.json");
}
@Nonnull
@Nullable
@Override
protected JBuilder<? extends IConstant> createBuilder(@Nonnull OldVar entity) {
return new OldVar.Builder(entity);
}
@Nonnull
@Override
protected PersistedEntitiesContainer<OldVar> createPersistenceContainer() {
return new OldVars();
protected Jsonable toJsonable(@NonNull IConstant constant) {
return CppVariable.builder(constant).build();
}
private void addSafely(@Nonnull String name) {
if (!contains(name)) {
addSafely(new OldVar.Builder(name, (String) null));
}
}
@Nonnull
@Override
protected OldVar transform(@Nonnull IConstant entity) {
if (entity instanceof OldVar) {
return (OldVar) entity;
} else {
return new OldVar.Builder(entity).create();
addSafely(CppVariable.builder(name).build().toJsclBuilder());
}
}
@ -174,13 +160,7 @@ public class VariablesRegistry extends BaseEntitiesRegistry<IConstant, OldVar> {
}
@Override
public Category getCategory(@Nonnull IConstant var) {
for (VarCategory category : VarCategory.values()) {
if (category.isInCategory(var)) {
return category;
}
}
return null;
public Category getCategory(@Nonnull IConstant variable) {
return Entities.getCategory(variable, VariablesCategory.values());
}
}

View File

@ -0,0 +1,20 @@
package org.solovyev.android.calculator.entities;
import android.support.annotation.StringRes;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
public interface Category<E extends MathEntity> {
int ordinal();
@Nonnull
String name();
boolean isInCategory(@Nonnull E entity);
@StringRes
int title();
}

View File

@ -0,0 +1,25 @@
package org.solovyev.android.calculator.entities;
import android.support.annotation.NonNull;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class Entities {
private Entities() {
}
@Nullable
public static <E extends MathEntity, C extends Category<E>> Category<E> getCategory(@Nonnull E entity, @NonNull C[] categories) {
for (C category : categories) {
if (category.isInCategory(entity)) {
return category;
}
}
return null;
}
}

View File

@ -4,21 +4,26 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import jscl.math.function.CustomFunction;
import jscl.math.function.IFunction;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.common.JBuilder;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
public class CppFunction implements Jsonable, Parcelable {
public static final Json.Creator<CppFunction> JSON_CREATOR = new Json.Creator<CppFunction>() {
@ -46,7 +51,7 @@ public class CppFunction implements Jsonable, Parcelable {
private static final String JSON_DESCRIPTION = "d";
@Nonnull
protected final List<String> parameters = new ArrayList<>();
protected int id;
protected int id = NO_ID;
@Nonnull
protected String name;
@Nonnull
@ -55,13 +60,11 @@ public class CppFunction implements Jsonable, Parcelable {
protected String description = "";
private CppFunction(@Nonnull String name, @Nonnull String body) {
this.id = NO_ID;
this.name = name;
this.body = body;
}
private CppFunction(@NonNull JSONObject json) throws JSONException {
id = NO_ID;
final JSONArray array = json.optJSONArray(JSON_PARAMETERS);
if (array != null) {
for (int i = 0; i < array.length(); i++) {
@ -180,7 +183,7 @@ public class CppFunction implements Jsonable, Parcelable {
}
@Nonnull
public CustomFunction.Builder toCustomFunctionBuilder() {
public JBuilder<? extends Function> toJsclBuilder() {
final CustomFunction.Builder builder = new CustomFunction.Builder(name, parameters, body);
builder.setDescription(description);
if (id != NO_ID) {
@ -235,13 +238,6 @@ public class CppFunction implements Jsonable, Parcelable {
return this;
}
@Nonnull
public Builder withBody(@NonNull String body) {
Check.isTrue(!built);
function.body = body;
return this;
}
@Nonnull
public CppFunction build() {
built = true;

View File

@ -78,7 +78,6 @@ import javax.inject.Inject;
import butterknife.Bind;
import butterknife.ButterKnife;
import jscl.math.function.CustomFunction;
import jscl.math.function.Function;
import static org.solovyev.android.calculator.function.CppFunction.NO_ID;
@ -213,7 +212,7 @@ public class EditFunctionFragment extends BaseDialogFragment implements View.OnC
showRemovalDialog(function);
return;
}
final CustomFunction entity = function.toCustomFunctionBuilder().create();
final Function entity = function.toJsclBuilder().create();
functionsRegistry.remove(entity);
calculator.fireCalculatorEvent(CalculatorEventType.function_removed, entity, this);
dismiss();
@ -317,7 +316,7 @@ public class EditFunctionFragment extends BaseDialogFragment implements View.OnC
.withParameters(collectParameters())
.withDescription(descriptionView.getText().toString()).build();
final Function oldFunction = isNewFunction() ? null : functionsRegistry.getById(function.id);
functionsRegistry.add(newFunction.toCustomFunctionBuilder(), oldFunction);
functionsRegistry.add(newFunction.toJsclBuilder(), oldFunction);
return true;
} catch (RuntimeException e) {
setError(bodyLabel, e.getLocalizedMessage());

View File

@ -20,20 +20,25 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
package org.solovyev.android.calculator.function;
import android.support.annotation.StringRes;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.entities.Category;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
import jscl.math.function.ArcTrigonometric;
import jscl.math.function.Comparison;
import jscl.math.function.Function;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public enum FunctionCategory implements Category {
public enum FunctionCategory implements Category<Function> {
my(R.string.c_fun_category_my) {
@Override
@ -91,6 +96,4 @@ public enum FunctionCategory implements Category {
public int title() {
return title;
}
public abstract boolean isInCategory(@Nonnull Function function);
}

View File

@ -20,12 +20,42 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
package org.solovyev.android.calculator.function;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
public interface PersistedEntity {
@Root(name = "function")
public class OldFunction implements Serializable {
@Transient
public Integer id;
@Element
public String name;
@Element(name = "body")
public String content;
@ElementList(type = String.class)
@Nonnull
String getName();
public List<String> parameterNames = new ArrayList<String>();
@Element
public boolean system;
@Element(required = false)
@Nonnull
public String description = "";
public OldFunction() {
}
}

View File

@ -20,14 +20,12 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
package org.solovyev.android.calculator.function;
import android.text.TextUtils;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.PersistedEntitiesContainer;
import org.solovyev.android.calculator.function.CppFunction;
import java.util.ArrayList;
import java.util.List;
@ -35,12 +33,13 @@ import java.util.List;
import javax.annotation.Nonnull;
@Root(name = "Functions")
public class OldFunctions implements PersistedEntitiesContainer<OldFunction> {
public class OldFunctions {
public static final String PREFS_KEY = "org.solovyev.android.calculator.CalculatorModel_functions";
@ElementList(type = OldFunction.class)
private List<OldFunction> functions = new ArrayList<>();
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@ElementList(type = OldFunction.class, name = "functions")
public List<OldFunction> list = new ArrayList<>();
public OldFunctions() {
}
@ -48,20 +47,16 @@ public class OldFunctions implements PersistedEntitiesContainer<OldFunction> {
@Nonnull
public static List<CppFunction> toCppFunctions(@Nonnull OldFunctions oldFunctions) {
final List<CppFunction> functions = new ArrayList<>();
for (OldFunction oldFunction : oldFunctions.functions) {
final String name = oldFunction.getName();
final String body = oldFunction.getContent();
for (OldFunction oldFunction : oldFunctions.list) {
final String name = oldFunction.name;
final String body = oldFunction.content;
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(body)) {
continue;
}
functions.add(CppFunction.builder(name, body)
.withParameters(oldFunction.getParameterNames())
.withDescription(oldFunction.getDescription()).build());
.withParameters(oldFunction.parameterNames)
.withDescription(oldFunction.description).build());
}
return functions;
}
public List<OldFunction> getEntities() {
return functions;
}
}

View File

@ -31,27 +31,35 @@ import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.ClipboardManager;
import android.text.TextUtils;
import android.view.*;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import com.melnykov.fab.FloatingActionButton;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.BaseFragment;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.Category;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.R;
import org.solovyev.android.views.llm.DividerItemDecoration;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import butterknife.Bind;
import butterknife.ButterKnife;
public abstract class BaseEntitiesFragment<E extends MathEntity> extends BaseFragment {
@ -221,7 +229,7 @@ public abstract class BaseEntitiesFragment<E extends MathEntity> extends BaseFra
public void bind(@Nonnull E entity) {
this.entity = entity;
textView.setText(String.valueOf(entity));
textView.setText(entity.getName());
final String description = getDescription(entity);
if (!Strings.isEmpty(description)) {

View File

@ -31,7 +31,7 @@ import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.VarCategory;
import org.solovyev.android.calculator.variables.VariablesCategory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -57,11 +57,11 @@ public class CalculatorVarsActivity extends BaseActivity implements CalculatorEv
final CalculatorFragmentType fragmentType = CalculatorFragmentType.variables;
for (VarCategory category : VarCategory.values()) {
for (VariablesCategory category : VariablesCategory.values()) {
final Bundle fragmentParameters;
if (category == VarCategory.my && bundle != null) {
if (category == VariablesCategory.my && bundle != null) {
BaseEntitiesFragment.putCategory(bundle, category.name());
fragmentParameters = bundle;
} else {

View File

@ -26,7 +26,7 @@ import android.os.Bundle;
import android.os.Parcelable;
import org.solovyev.android.calculator.BaseActivity;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.FunctionCategory;
import org.solovyev.android.calculator.function.FunctionCategory;
import org.solovyev.android.calculator.R;
import javax.annotation.Nullable;

View File

@ -31,6 +31,7 @@ import com.squareup.otto.Subscribe;
import jscl.math.function.Function;
import jscl.math.function.IFunction;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.function.CppFunction;
import org.solovyev.android.calculator.function.EditFunctionFragment;
import org.solovyev.common.text.Strings;

View File

@ -29,7 +29,7 @@ import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.OperatorCategory;
import org.solovyev.android.calculator.operators.OperatorCategory;
import org.solovyev.android.calculator.R;
import javax.annotation.Nonnull;

View File

@ -27,6 +27,7 @@ import android.view.ContextMenu;
import android.view.MenuItem;
import jscl.math.operator.Operator;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;

View File

@ -45,7 +45,7 @@ import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.OldVar;
import org.solovyev.android.calculator.variables.OldVar;
import org.solovyev.common.text.Strings;
import java.util.Arrays;

View File

@ -145,7 +145,7 @@ public class VarEditorSaver<T extends MathEntity> implements View.OnClickListene
if (error != null) {
Locator.getInstance().getNotifier().showMessage(error, MessageType.error);
} else {
VariablesRegistry.saveVariable(mathRegistry, varBuilder, editedInstance, source, true);
VariablesRegistry.add(mathRegistry, varBuilder, editedInstance, source);
}
}
}

View File

@ -29,7 +29,6 @@ import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import com.melnykov.fab.FloatingActionButton;
import com.squareup.otto.Bus;
import org.solovyev.android.calculator.AppComponent;
@ -38,7 +37,7 @@ import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.Category;
import org.solovyev.android.calculator.entities.Category;
import org.solovyev.android.calculator.Change;
import org.solovyev.android.calculator.Keyboard;
import org.solovyev.android.calculator.Locator;
@ -114,7 +113,6 @@ public class VariablesFragment extends BaseEntitiesFragment<IConstant> implement
public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState);
final FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.fab);
fab.setVisibility(View.VISIBLE);
fab.attachToRecyclerView(recyclerView);
fab.setOnClickListener(new View.OnClickListener() {

View File

@ -1,81 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
import android.content.SharedPreferences;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.calculator.PersistedEntitiesContainer;
import org.solovyev.android.calculator.PersistedEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.StringWriter;
public class EntityDao<T extends PersistedEntity> {
@Nonnull
private final String preferenceString;
@Nonnull
private final Class<? extends PersistedEntitiesContainer<T>> persistenceContainerClass;
@Nonnull
private final SharedPreferences preferences;
public EntityDao(@Nonnull String preferenceString,
@Nonnull Class<? extends PersistedEntitiesContainer<T>> persistenceContainerClass, @Nonnull SharedPreferences preferences) {
this.preferenceString = preferenceString;
this.persistenceContainerClass = persistenceContainerClass;
this.preferences = preferences;
}
public void save(@Nonnull PersistedEntitiesContainer<T> container) {
final SharedPreferences.Editor editor = preferences.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(preferenceString, sw.toString());
editor.apply();
}
@Nullable
public PersistedEntitiesContainer<T> load() {
final String value = preferences.getString(preferenceString, null);
if (value != null) {
final Serializer serializer = new Persister();
try {
return serializer.read(persistenceContainerClass, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return null;
}
}

View File

@ -1,159 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient;
import org.solovyev.android.calculator.PersistedEntity;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.Strings;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import jscl.math.function.IFunction;
@Root(name = "function")
public class OldFunction implements IFunction, PersistedEntity, Serializable {
@Transient
private Integer id;
@Element
private String name;
@Element(name = "body")
private String content;
@ElementList(type = String.class)
@Nonnull
private List<String> parameterNames = new ArrayList<String>();
@Element
private boolean system;
@Element(required = false)
@Nonnull
private String description = "";
public OldFunction() {
}
public static OldFunction fromIFunction(@Nonnull IFunction function) {
final OldFunction result = new OldFunction();
copy(result, function);
return result;
}
private static void copy(@Nonnull OldFunction target,
@Nonnull IFunction source) {
target.name = source.getName();
target.content = source.getContent();
target.description = Strings.getNotEmpty(source.getDescription(), "");
target.system = source.isSystem();
if (source.isIdDefined()) {
target.id = source.getId();
}
target.parameterNames = new ArrayList<>(source.getParameterNames());
}
@Override
public void copy(@Nonnull MathEntity mathEntity) {
if (mathEntity instanceof IFunction) {
copy(this, (IFunction) mathEntity);
} else {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + mathEntity.getClass());
}
}
@Override
public String toJava() {
return String.valueOf(this.content);
}
@Override
public String toString() {
return "AFunction{" +
"name='" + name + '\'' +
", parameterNames=" + parameterNames +
", content='" + content + '\'' +
'}';
}
@Nonnull
public String getName() {
return name;
}
public void setName(@Nonnull String name) {
this.name = name;
}
@Override
public boolean isSystem() {
return system;
}
@Nonnull
@Override
public Integer getId() {
return this.id;
}
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
@Override
public boolean isIdDefined() {
return this.id != null;
}
@Nonnull
public String getContent() {
return content;
}
public void setContent(@Nonnull String content) {
this.content = content;
}
@Nonnull
@Override
public String getDescription() {
return this.description;
}
@Nonnull
public List<String> getParameterNames() {
return parameterNames;
}
}

View File

@ -20,14 +20,23 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
package org.solovyev.android.calculator.operators;
import android.support.annotation.StringRes;
import jscl.math.operator.*;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.entities.Category;
import javax.annotation.Nonnull;
public enum OperatorCategory implements Category {
import jscl.math.operator.Derivative;
import jscl.math.operator.IndefiniteIntegral;
import jscl.math.operator.Integral;
import jscl.math.operator.Operator;
import jscl.math.operator.Product;
import jscl.math.operator.Sum;
public enum OperatorCategory implements Category<Operator> {
my(R.string.c_fun_category_my) {
@Override
@ -72,8 +81,6 @@ public enum OperatorCategory implements Category {
this.title = title;
}
public abstract boolean isInCategory(@Nonnull Operator operator);
@Override
public int title() {
return title;

View File

@ -1,15 +1,171 @@
package org.solovyev.android.calculator.variables;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.function.CppFunction;
import org.solovyev.android.calculator.json.Json;
import org.solovyev.android.calculator.json.Jsonable;
import org.solovyev.common.JBuilder;
import javax.annotation.Nonnull;
import jscl.math.function.IConstant;
import static com.google.common.base.Strings.nullToEmpty;
public class CppVariable implements Jsonable {
public static final Json.Creator<CppVariable> JSON_CREATOR = new Json.Creator<CppVariable>() {
@NonNull
@Override
public CppVariable create(@NonNull JSONObject json) throws JSONException {
return new CppVariable(json);
}
};
private static final String JSON_NAME = "n";
private static final String JSON_VALUE = "v";
private static final String JSON_DESCRIPTION = "d";
protected int id = CppFunction.NO_ID;
@Nonnull
protected String name;
@Nonnull
protected String value = "";
@Nonnull
protected String description = "";
protected boolean system;
private CppVariable(@Nonnull String name) {
this.name = name;
}
protected CppVariable(@Nonnull CppVariable that) {
this.id = that.id;
this.name = that.name;
this.value = that.value;
this.description = that.description;
this.system = that.system;
}
protected CppVariable(@NonNull IConstant that) {
id = that.isIdDefined() ? that.getId() : CppFunction.NO_ID;
name = that.getName();
value = nullToEmpty(that.getValue());
description = nullToEmpty(that.getDescription());
system = that.isSystem();
}
private CppVariable(@NonNull JSONObject json) throws JSONException {
this.name = json.getString(JSON_NAME);
this.value = json.optString(JSON_DESCRIPTION);
this.description = json.optString(JSON_DESCRIPTION);
}
@NonNull
public static CppVariable.Builder builder(@NonNull String name) {
return new Builder(name);
}
@NonNull
public static Builder builder(@NonNull IConstant constant) {
return new Builder(constant);
}
@Nonnull
@Override
public JSONObject toJson() throws JSONException {
return null;
final JSONObject json = new JSONObject();
json.put(JSON_NAME, name);
if (!TextUtils.isEmpty(value)) {
json.put(JSON_VALUE, value);
}
if (!TextUtils.isEmpty(description)) {
json.put(JSON_DESCRIPTION, description);
}
return json;
}
@Nonnull
public JBuilder<? extends IConstant> toJsclBuilder() {
return new JBuilder<IConstant>() {
@Nonnull
@Override
public IConstant create() {
return new JsclConstant(CppVariable.this);
}
};
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CppVariable)) return false;
CppVariable that = (CppVariable) o;
if (id != that.id) return false;
if (!name.equals(that.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + name.hashCode();
return result;
}
public static class Builder {
@NonNull
private final CppVariable variable;
private boolean built;
private Builder(@NonNull String name) {
variable = new CppVariable(name);
}
private Builder(@NonNull IConstant constant) {
variable = new CppVariable(constant);
}
@Nonnull
public Builder withDescription(@Nonnull String description) {
Check.isTrue(!built);
variable.description = description;
return this;
}
@Nonnull
public Builder withValue(@NonNull String value) {
Check.isTrue(!built);
variable.value = value;
return this;
}
@Nonnull
public Builder withSystem(boolean system) {
Check.isTrue(!built);
variable.system = system;
return this;
}
@Nonnull
public Builder withId(int id) {
Check.isTrue(!built);
variable.id = id;
return this;
}
@Nonnull
public CppVariable build() {
built = true;
return variable;
}
}
}

View File

@ -0,0 +1,116 @@
package org.solovyev.android.calculator.variables;
import com.google.common.base.Strings;
import org.solovyev.android.calculator.function.CppFunction;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.math.function.Constant;
import jscl.math.function.IConstant;
class JsclConstant extends CppVariable implements IConstant {
private Double doubleValue;
private Constant constant;
JsclConstant(@Nonnull CppVariable variable) {
super(variable);
}
@Nonnull
@Override
public Constant getConstant() {
if (constant == null) {
constant = new Constant(name);
}
return constant;
}
@Nullable
@Override
public String getDescription() {
return description;
}
@Override
public boolean isDefined() {
return !Strings.isNullOrEmpty(value);
}
@Nullable
@Override
public String getValue() {
return value;
}
@Nullable
@Override
public Double getDoubleValue() {
if (doubleValue != null) {
return doubleValue;
}
if (!Strings.isNullOrEmpty(value)) {
try {
doubleValue = Double.valueOf(value);
} catch (NumberFormatException e) {
// do nothing - string is not a double
}
}
return doubleValue;
}
@Nonnull
@Override
public String toJava() {
return Strings.nullToEmpty(value);
}
@Nonnull
@Override
public String getName() {
return name;
}
@Override
public boolean isSystem() {
return system;
}
@Nonnull
@Override
public Integer getId() {
return id == CppFunction.NO_ID ? null : id;
}
@Override
public void setId(@Nonnull Integer id) {
this.id = id;
}
@Override
public boolean isIdDefined() {
return id != CppFunction.NO_ID;
}
@Override
public void copy(@Nonnull MathEntity o) {
if (!(o instanceof IConstant)) {
throw new IllegalArgumentException("Trying to make a copy of unsupported type: " + o.getClass());
}
final IConstant that = ((IConstant) o);
this.name = that.getName();
this.value = that.getValue();
this.description = that.getDescription();
this.system = that.isSystem();
if (that.isIdDefined()) {
this.id = that.getId();
} else {
this.id = CppFunction.NO_ID;
}
this.doubleValue = null;
this.constant = null;
}
}

View File

@ -20,12 +20,12 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
package org.solovyev.android.calculator.variables;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Transient;
import org.solovyev.android.calculator.PersistedEntity;
import org.solovyev.android.calculator.model.MathEntityBuilder;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.Strings;
@ -38,7 +38,7 @@ import jscl.math.function.ExtendedConstant;
import jscl.math.function.IConstant;
@Root(name = "var")
public class OldVar implements IConstant, PersistedEntity {
public class OldVar implements IConstant {
@Transient
private Integer id;
@ -234,7 +234,7 @@ public class OldVar implements IConstant, PersistedEntity {
return this;
}
protected Builder setSystem(boolean system) {
public Builder setSystem(boolean system) {
this.system = system;
return this;
}

View File

@ -20,45 +20,43 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
package org.solovyev.android.calculator.variables;
import android.text.TextUtils;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.PersistedEntitiesContainer;
import org.solovyev.android.calculator.variables.CppVariable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import static com.google.common.base.Strings.nullToEmpty;
@Root(name = "vars")
public class OldVars implements PersistedEntitiesContainer<OldVar> {
public class OldVars {
public static final String PREFS_KEY = "org.solovyev.android.calculator.CalculatorModel_vars";
@ElementList(type = OldVar.class)
private List<OldVar> vars = new ArrayList<OldVar>();
@ElementList(type = OldVar.class, name = "vars")
public List<OldVar> list = new ArrayList<OldVar>();
public OldVars() {
}
public List<OldVar> getEntities() {
return vars;
}
@Nonnull
public static List<CppVariable> toCppVariables(@Nonnull OldVars oldVariables) {
final List<CppVariable> variables = new ArrayList<>();
/*for (OldVar oldVar : oldVariables.vars) {
for (OldVar oldVar : oldVariables.list) {
final String name = oldVar.getName();
final String body = oldVar.getContent();
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(body)) {
if (TextUtils.isEmpty(name)) {
continue;
}
variables.add(CppFunction.builder(name, body)
.withParameters(oldVar.getParameterNames())
.withDescription(oldVar.getDescription()).build());
}*/
variables.add(CppVariable.builder(name)
.withValue(nullToEmpty(oldVar.getValue()))
.withDescription(nullToEmpty(oldVar.getDescription())).build());
}
return variables;
}
}

View File

@ -20,39 +20,40 @@
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
package org.solovyev.android.calculator.variables;
import android.support.annotation.StringRes;
import jscl.math.function.IConstant;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.entities.Category;
import javax.annotation.Nonnull;
public enum VarCategory implements Category {
import jscl.math.function.IConstant;
public enum VariablesCategory implements Category<IConstant> {
my(R.string.c_var_my) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return !var.isSystem();
public boolean isInCategory(@Nonnull IConstant variable) {
return !variable.isSystem();
}
},
system(R.string.c_var_system) {
@Override
public boolean isInCategory(@Nonnull IConstant var) {
return var.isSystem();
public boolean isInCategory(@Nonnull IConstant variable) {
return variable.isSystem();
}
};
@StringRes
private final int title;
VarCategory(@StringRes int title) {
VariablesCategory(@StringRes int title) {
this.title = title;
}
public abstract boolean isInCategory(@Nonnull IConstant var);
@Override
public int title() {
return title;

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2013 serso aka se.solovyev
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Contact details
~
~ Email: se.solovyev@gmail.com
~ Site: http://se.solovyev.org
-->
<LinearLayout
xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/main_fragment_layout"
style="@style/CppFragment"
a:layout_width="match_parent"
a:layout_height="match_parent">
<TextView
a:id="@+id/fragment_title"
style="@style/CppFragmentTitle"
a:layout_width="match_parent"
a:layout_height="wrap_content" />
<include layout="@layout/ad" />
<FrameLayout
a:layout_width="match_parent"
a:layout_height="match_parent">
<ListView style="@style/CppListView" />
<com.melnykov.fab.FloatingActionButton
a:id="@+id/fab"
style="@style/CppFab"
a:src="@drawable/ic_add_white_36dp" />
</FrameLayout>
</LinearLayout>

View File

@ -31,7 +31,6 @@ import org.mockito.Mockito;
import org.robolectric.fakes.RoboSharedPreferences;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.calculator.model.EntityDao;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import java.io.ByteArrayInputStream;
@ -99,8 +98,6 @@ public class CalculatorTestUtils {
@Nonnull
static Engine newCalculatorEngine() {
final EntityDao entityDao = Mockito.mock(EntityDao.class);
final JsclMathEngine jsclEngine = JsclMathEngine.getInstance();
final VariablesRegistry variablesRegistry = new VariablesRegistry(jsclEngine);

View File

@ -25,7 +25,7 @@ package org.solovyev.android.calculator;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.solovyev.android.calculator.model.OldVar;
import org.solovyev.android.calculator.variables.OldVar;
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
import java.text.DecimalFormatSymbols;

View File

@ -31,6 +31,7 @@ import org.solovyev.android.calculator.CalculatorEvalException;
import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.variables.OldVar;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

View File

@ -28,6 +28,7 @@ import org.solovyev.android.calculator.AbstractCalculatorTest;
import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.variables.OldVar;
import jscl.AngleUnit;
import jscl.MathEngine;

View File

@ -30,6 +30,8 @@ import org.junit.Test;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.function.OldFunction;
import org.solovyev.android.calculator.function.OldFunctions;
import org.solovyev.common.Objects;
import org.solovyev.common.equals.CollectionEqualizer;
@ -145,13 +147,13 @@ public class OldFunctionsTest {
private void assertEquals(@Nonnull final OldFunction expected,
@Nonnull OldFunction actual) {
//Assert.assertEquals(expected.getId(), actual.getId());
Assert.assertEquals(expected.getContent(), actual.getContent());
Assert.assertEquals(expected.getDescription(), actual.getDescription());
Assert.assertEquals(expected.getName(), actual.getName());
Assert.assertThat(actual.getParameterNames(), new BaseMatcher<List<String>>() {
Assert.assertEquals(expected.content, actual.content);
Assert.assertEquals(expected.description, actual.description);
Assert.assertEquals(expected.name, actual.name);
Assert.assertThat(actual.parameterNames, new BaseMatcher<List<String>>() {
@Override
public boolean matches(Object item) {
return Objects.areEqual(expected.getParameterNames(), (List<String>) item, new CollectionEqualizer<String>(null));
return Objects.areEqual(expected.parameterNames, (List<String>) item, new CollectionEqualizer<String>(null));
}
@Override

View File

@ -25,6 +25,8 @@ package org.solovyev.android.calculator.model;
import org.junit.Test;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.calculator.variables.OldVar;
import org.solovyev.android.calculator.variables.OldVars;
import java.io.StringWriter;
@ -59,9 +61,9 @@ public class OldVarTest {
public void testXml() throws Exception {
final OldVars vars = new OldVars();
OldVar first = new OldVar.Builder("e", Math.E).setDescription("description").setSystem(true).create();
vars.getEntities().add(first);
vars.list.add(first);
OldVar second = new OldVar.Builder(";", 3d).setSystem(true).create();
vars.getEntities().add(second);
vars.list.add(second);
final StringWriter sw = new StringWriter();
final Serializer serializer = new Persister();
@ -70,8 +72,8 @@ public class OldVarTest {
assertEquals(xml, sw.toString());
final OldVars result = serializer.read(OldVars.class, xml);
final IConstant actualFirst = result.getEntities().get(0);
final IConstant actualSecond = result.getEntities().get(1);
final IConstant actualFirst = result.list.get(0);
final IConstant actualSecond = result.list.get(1);
areEqual(first, actualFirst);
areEqual(second, actualSecond);