private static async Task LoadJsonModelIntoGeneratedJsonSchemaView( ViewStack viewStack, ModelToJsonSchema schemaGenerator, JsonSchema schema, string jsonModel) { JObject model = JsonReader.GetReader().Read <JObject>(jsonModel); JsonSchemaToView viewGenerator = new JsonSchemaToView(schemaGenerator); GameObject generatedView = await viewGenerator.ToView(schema); viewStack.ShowView(generatedView); var presenter = new JsonSchemaPresenter(viewGenerator); presenter.targetView = generatedView; Log.d("Model BEFORE changes: " + model.ToPrettyString()); var changedModel = await presenter.LoadModelIntoView(model.DeepClone() as JObject); await JsonSchemaPresenter.ChangesSavedViaConfirmButton(generatedView); Log.d("Model AFTER changes: " + changedModel.ToPrettyString()); viewStack.SwitchBackToLastView(generatedView); var changedFields = MergeJson.GetDiff(model, changedModel); Log.d("Fields changed: " + changedFields?.ToPrettyString()); }
private static void ShowChanges <T>(object action, T previousState, T newState) { try { JToken diff = MergeJson.GetDiff(previousState, newState); Log.d(asJson("" + action.GetType().Name, action), asJson("previousState -> newState diff", diff)); } catch (Exception e) { Log.e(e); } }
public void ExampleUsage1() { MyClass1 original = new MyClass1() { name = "1", child = new MyClass1() { name = "2" } }; MyClass1 copy = original.DeepCopyViaJson(); Assert.Null(MergeJson.GetDiff(original, copy)); // No diff between original and copy AssertV2.AreEqualJson(original, copy); // WIll use MergeJson.GetDiff internally Assert.Equal(original.child.name, copy.child.name); // Modify the copy, changing the copy will not change the original: copy.child.name = "Some new name.."; // Check that the change was only done in the copy and not the original: Assert.NotEqual(original.child.name, copy.child.name); Assert.NotNull(MergeJson.GetDiff(original, copy)); // Objects that impl. IClonable can also ShallowCopy (will call .Clone internally): MyClass1 shallowCopy = original.ShallowCopyViaClone(); Assert.NotSame(original, shallowCopy); Assert.Same(original.child, shallowCopy.child); }
private static void AssertActionDidNotChangeDuringDispatch(object actionBeforeDispatch, object actionAfter) { JToken diff = MergeJson.GetDiff(actionBeforeDispatch, actionAfter); if (!diff.IsNullOrEmpty()) { throw Log.e("The action was changed by dispatching it, check reducers: " + diff.ToPrettyString()); } }
public void ExampleUsage2() { MyClass1 originalObj = new MyClass1() { myString = "abc", myString2 = "def" }; MyClass1 copy1 = originalObj.DeepCopyViaJson(); copy1.myString = "abcd"; copy1.complexField = new MyClass1() { myString = "123", myString2 = "456" }; copy1.complexField.complexList = new List <MyClass1>() { new MyClass1() { myString = "listEntry1" } }; MyClass1 copy2 = originalObj.DeepCopyViaJson(); copy2.myString2 = "defg"; copy2.myString = "123"; copy2.complexField = new MyClass1() { myString = "zyx" }; copy2.complexField.complexList = new List <MyClass1>() { new MyClass1() { myString = "listEntry2" } }; var merge = MergeJson.Merge(originalObj, copy1, copy2); Assert.True(merge.hasMergeConflict); // Parsed conflicts returns an easy to iterate through array: var parsedConflicts = merge.GetParsedMergeConflicts(); var firstConflict = parsedConflicts.First(); Assert.Equal("myString", firstConflict.fieldName); Assert.Equal("abcd", "" + firstConflict.oldValue); Assert.Equal("123", "" + firstConflict.newValue); //Log.d("merge2.conflicts=" + JsonWriter.AsPrettyString(merge2.conflicts)); //Log.d("parsedConflicts=" + JsonWriter.AsPrettyString(parsedConflicts)); }
private static async Task LoadModelIntoGeneratedView(ViewStack viewStack, ModelToJsonSchema schemaGenerator, JsonSchema schema) { MyUserModel model = NewExampleUserInstance(); { await Dialog.ShowInfoDialog("Manually connecting the model instance to the view", "First an example to connect the " + "model to a generated view via a manual presenter 'MyManualPresenter1'", "Show manual presenter example"); var viewGenerator = new JsonSchemaToView(schemaGenerator); GameObject generatedView = await viewGenerator.ToView(schema); viewStack.ShowView(generatedView); var presenter = new MyManualPresenter1(); presenter.targetView = generatedView; Log.d("Model BEFORE changes: " + JsonWriter.AsPrettyString(model)); await presenter.LoadModelIntoView(model); viewStack.SwitchBackToLastView(generatedView); Log.d("Model AFTER changes: " + JsonWriter.AsPrettyString(model)); } { await Dialog.ShowInfoDialog("Using JsonSchemaPresenter to autmatically connect the model instance and view", "The second option is to use a generic JObjectPresenter to connect the model to the generated view", "Show JsonSchemaPresenter example"); var viewGenerator = new JsonSchemaToView(schemaGenerator); GameObject generatedView = await viewGenerator.ToView(schema); viewStack.ShowView(generatedView); var presenter = new JsonSchemaPresenter(viewGenerator); presenter.targetView = generatedView; Log.d("Model BEFORE changes: " + JsonWriter.AsPrettyString(model)); MyUserModel changedModel = await presenter.LoadViaJsonIntoView(model); viewStack.SwitchBackToLastView(generatedView); Log.d("Model AFTER changes: " + JsonWriter.AsPrettyString(changedModel)); var changedFields = MergeJson.GetDiff(model, changedModel); Log.d("Fields changed: " + changedFields?.ToPrettyString()); } }
private async Task ShowModelInstanceInView() { // Get the previously created view (see above) var uiView = gameObject.GetChild(0); AssertV2.IsNotNull(uiView, "uiView"); // Create some example model instance: var modelInstance = Ui18_1_JsonSchemaUiGenerator.NewExampleUserInstance(); JsonSchemaPresenter p = new JsonSchemaPresenter(JsonSchemaToView.NewViewGenerator()); p.targetView = uiView; var changedInstance = await p.LoadViaJsonIntoView(modelInstance); uiView.Destroy(); // Close the view by destroying it after the user done with it var changedFields = MergeJson.GetDiff(modelInstance, changedInstance); Log.d("Fields changed: " + changedFields?.ToPrettyString()); }
public static bool LogAnyDiffToNewFieldViews(this Dictionary <string, FieldView> self, Dictionary <string, FieldView> newFieldViews) { // First compare all field views that are found both in the list of old and new views and print out the changes: self.CheckIntersectingFieldViewsForChanges(newFieldViews, (oldFieldView, newFieldView, _) => { AssertV2.IsNotNull(oldFieldView.field, "oldFieldView.field"); AssertV2.IsNotNull(newFieldView.field, "newFieldView.field"); var diff = MergeJson.GetDiff(oldFieldView.field, newFieldView.field); if (!diff.IsNullOrEmpty()) { Log.e($"Detected changed field view '{oldFieldView.fullPath}' that needs UI update! " + $"Detected changes: {diff.ToPrettyString()}", oldFieldView.gameObject); } }); // Second the list of views that have to be removed from the old UI is listed (and auto deleted if desired): foreach (var removed in self.GetOutdatedFieldViewsToDelete(newFieldViews)) { Log.e($"The field '{removed.Key}' was removed from the model and HAS TO BE DELETED from the UI", removed.Value.gameObject); } // Finally check if there are any missing views in the old UI that have to be manually added (picked from the new UI): return(self.FindNewFieldViewsAddedIn(newFieldViews)); }
public void ExampleUsage1() { MyClass1 original = new MyClass1() { name = "1", child = new MyClass1() { name = "2", age = 3 } }; MyClass1 copy = original.DeepCopyViaJson(); Assert.Null(MergeJson.GetDiff(original, copy)); // No diff between original and copy AssertV2.AreEqualJson(original, copy); // AreEqualJson will use MergeJson.GetDiff internally Assert.Equal(original.child.name, copy.child.name); // Modify the copy, changing the copy will not change the original: copy.child.name = "Some new name.."; // Check that the change was only done in the copy and not the original: Assert.NotEqual(original.child.name, copy.child.name); JToken diffToOriginal = MergeJson.GetDiff(original, copy); Assert.NotNull(diffToOriginal); // Objects that impl. IClonable can also ShallowCopy (will call .Clone internally): MyClass1 shallowCopy = original.ShallowCopyViaClone(); Assert.NotSame(original, shallowCopy); Assert.Same(original.child, shallowCopy.child); // Applying a change to an existing target object is done using MergeJson.Patch: var oldName = original.child.name; MergeJson.Patch(original, diffToOriginal); // Apply the changes stored in the diff Assert.NotEqual(oldName, original.child.name); // The name field was updated Assert.Equal(copy.child.name, original.child.name); Assert.Equal(3, original.child.age); // The age field was not changed by the patch }
public void ExampleUsage1() { MyClass1 originalObj = new MyClass1() { myString = "abc", myString2 = "def" }; MyClass1 copy1 = originalObj.DeepCopyViaJson(); copy1.myString = "abcd"; copy1.complexField = new MyClass1() { myString = "123", myString2 = "456" }; copy1.complexField.complexList = new List <MyClass1>() { new MyClass1() { myString = "listEntry1" } }; MyClass1 copy2 = originalObj.DeepCopyViaJson(); copy2.myString2 = "defg"; var merge = MergeJson.Merge(originalObj, copy1, copy2); Assert.False(merge.hasMergeConflict); // Parse the merged result back into a MyClass1 object: MyClass1 mergeResult1 = merge.GetResult(); // The changes from both copies were merged correctly: Assert.Equal(copy1.myString, mergeResult1.myString); Assert.Equal(copy2.myString2, mergeResult1.myString2); }
private static bool HasDiff(object actionBeforeDispatch, object actionAfter, out JToken diff) { diff = MergeJson.GetDiff(actionBeforeDispatch, actionAfter); return(!diff.IsNullOrEmpty()); }