getOperatingSystem();
/**
* Checks if the editor is in read only mode.
* @return If the editor is in read only mode or if is not.
*/
boolean isReadOnly();
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/context/OperatingSystem.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.context;
import java.util.stream.Stream;
public enum OperatingSystem {
DEFAULT("DEFAULT"),
MACOS("MACOS"),
LINUX("LINUX"),
WINDOWS("WINDOWS");
private final String name;
OperatingSystem(final String name) {
this.name = name;
}
public String getName() {
return name;
}
public static OperatingSystem withName(final String name) {
return Stream.of(OperatingSystem.values())
.filter(os -> os.getName().equalsIgnoreCase(name))
.findFirst().orElseThrow(() -> new IllegalArgumentException("Name not recognized: " + name));
}
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/keyboardShortcuts/KeyboardShortcutsApiOpts.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.keyboardShortcuts;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;
@JsType
public class KeyboardShortcutsApiOpts {
public static final KeyboardShortcutsApiOpts DEFAULT = new KeyboardShortcutsApiOpts(Repeat.NO_REPEAT);
private final Repeat repeat;
public KeyboardShortcutsApiOpts(final Repeat repeat) {
this.repeat = repeat;
}
@JsProperty
public boolean getRepeat() {
return Repeat.REPEAT.equals(repeat);
}
/**
* Repetition mode for Keyboard Shortcuts.
*
* REPEAT - When pressing and holding a key, the same action will be fired multiple times.
* NO_REPEAT - When pressing and holding a key, the action will be only fired once.
*/
public enum Repeat {
REPEAT,
NO_REPEAT
}
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/stateControl/registry/DefaultRegistry.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.stateControl.registry;
public interface DefaultRegistry extends Registry {
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/stateControl/registry/Registry.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.stateControl.registry;
import java.util.List;
/**
* Represents a basic items registry.
*
* @param anything that can be registered.
*/
public interface Registry {
/**
* Registers an item into the registry
*
* @param item An item to register
*/
void register(final C item);
/**
* Peeks the last added item. Doesn't remove it.
*
* @return The last added item
*/
C peek();
/**
* Pops the last added item and removes it.
*
* @return The last added item
*/
C pop();
/**
* Sets the max number of items that can be stored on the registry.
*
* @param size A positive integer
*/
void setMaxSize(final int size);
/**
* Clears the registry
*/
void clear();
/**
* Determines if the registry is empty or not
*
* @return true if empty, false if not.
*/
boolean isEmpty();
/**
* Returns a {@link List} containing all the items in the registry
*
* @return A {@link List} of containing the registered items
*/
List getHistory();
/**
* Sets a {@link RegistryChangeListener} to be called when the registry changes.
*
* @param registryChangeListener A {@link RegistryChangeListener}
*/
void setRegistryChangeListener(RegistryChangeListener registryChangeListener);
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/stateControl/registry/RegistryChangeListener.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.stateControl.registry;
/**
* This functional interface represents the code that will be executed every time there's a change on a {@link Registry}
*/
@FunctionalInterface
public interface RegistryChangeListener {
/**
* Method that will be executed when a change on the registry happens
*/
void notifyRegistryChange();
}
================================================
FILE: appformer-client-api/src/main/java/org/appformer/client/stateControl/registry/impl/DefaultRegistryImpl.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.stateControl.registry.impl;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import org.appformer.client.stateControl.registry.DefaultRegistry;
import org.appformer.client.stateControl.registry.Registry;
import org.appformer.client.stateControl.registry.RegistryChangeListener;
/**
* The default generic implementation for the {@link Registry} type.
* It's implemented for achieving an in-memory and lightweight registry approach, don't do an overuse of it.
* Note: The Stack class behavior when using the iterator is not the expected one, so used
* ArrayDeque instead of an Stack to provide right iteration order.
*/
public class DefaultRegistryImpl implements DefaultRegistry {
private final Deque items = new ArrayDeque<>();
private int maxStackSize = 200;
private RegistryChangeListener registryChangeListener;
@Override
public void setMaxSize(final int size) {
if (size < 0) {
throw new IllegalArgumentException("The registry size should be a positive number");
}
this.maxStackSize = size;
}
@Override
public void register(final C item) {
addIntoStack(item);
notifyRegistryChange();
}
@Override
public void clear() {
items.clear();
notifyRegistryChange();
}
@Override
public List getHistory() {
return new ArrayList<>(items);
}
@Override
public void setRegistryChangeListener(final RegistryChangeListener registryChangeListener) {
this.registryChangeListener = registryChangeListener;
}
@Override
public C peek() {
return items.peek();
}
@Override
public C pop() {
C item = items.pop();
notifyRegistryChange();
return item;
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
private void notifyRegistryChange() {
if (registryChangeListener != null) {
registryChangeListener.notifyRegistryChange();
}
}
private void addIntoStack(final C item) {
if (null != item) {
if ((items.size() + 1) > maxStackSize) {
items.removeLast();
}
items.push(item);
}
}
}
================================================
FILE: appformer-client-api/src/main/resources/META-INF/ErraiApp.properties
================================================
#
# Copyright 2020 Red Hat, Inc. and/or its affiliates.
#
# 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.
#
#
# ErraiApp.properties
#
# Do not remove, even if empty!
#
# This is a marker file. When it is detected inside a JAR or at the
# top of any classpath, the subdirectories are scanned for deployable
# components. As such, all Errai application modules in a project
# should contain an ErraiApp.properties at the root of all classpaths
# that you wish to be scanned.
#
# There are also some configuration options that can be set in this
# file, although it is rarely necessary. See the documentation at
# https://docs.jboss.org/author/display/ERRAI/ErraiApp.properties
# for details.
================================================
FILE: appformer-client-api/src/main/resources/org/appformer/AppformerClientAPI.gwt.xml
================================================
================================================
FILE: appformer-client-api/src/test/java/org/appformer/client/stateControl/registry/impl/DefaultRegistryImplTest.java
================================================
/*
* Copyright 2020 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.appformer.client.stateControl.registry.impl;
import org.appformer.client.stateControl.registry.RegistryChangeListener;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class DefaultRegistryImplTest {
private static final Command COMMAND1 = new Command(1);
private static final Command COMMAND2 = new Command(2);
private static final Command COMMAND3 = new Command(3);
private static final Command COMMAND4 = new Command(4);
@Mock
private RegistryChangeListener changeListener;
private DefaultRegistryImpl registry;
@Before
public void init() {
registry = new DefaultRegistryImpl<>();
registry.setRegistryChangeListener(changeListener);
}
@Test
public void basicTest() {
registry.register(COMMAND1);
registry.register(COMMAND2);
registry.register(COMMAND3);
registry.register(COMMAND4);
verify(changeListener, times(4)).notifyRegistryChange();
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.hasSize(4)
.containsExactly(COMMAND4, COMMAND3, COMMAND2, COMMAND1);
Assertions.assertThat(registry.peek())
.isSameAs(COMMAND4);
Assertions.assertThat(registry.getHistory())
.hasSize(4)
.containsExactly(COMMAND4, COMMAND3, COMMAND2, COMMAND1);
Assertions.assertThat(registry.pop())
.isSameAs(COMMAND4);
verify(changeListener, times(5)).notifyRegistryChange();
Assertions.assertThat(registry.getHistory())
.hasSize(3)
.containsExactly(COMMAND3, COMMAND2, COMMAND1);
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.pop())
.isSameAs(COMMAND3);
verify(changeListener, times(6)).notifyRegistryChange();
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.hasSize(2)
.containsExactly(COMMAND2, COMMAND1);
registry.clear();
verify(changeListener, times(7)).notifyRegistryChange();
assertTrue(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.isEmpty();
}
@Test
public void testAddReachingMax() {
registry.setMaxSize(2);
registry.register(COMMAND1);
registry.register(COMMAND2);
verify(changeListener, times(2)).notifyRegistryChange();
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.hasSize(2)
.containsExactly(COMMAND2, COMMAND1);
registry.register(COMMAND3);
verify(changeListener, times(3)).notifyRegistryChange();
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.hasSize(2)
.containsExactly(COMMAND3, COMMAND2);
registry.register(COMMAND4);
verify(changeListener, times(4)).notifyRegistryChange();
assertFalse(registry.isEmpty());
Assertions.assertThat(registry.getHistory())
.hasSize(2)
.containsExactly(COMMAND4, COMMAND3);
}
@Test
public void testSettingWrongMax() {
Assertions.assertThatThrownBy(() -> registry.setMaxSize(-1))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("The registry size should be a positive number");
}
public static class Command {
private Integer id;
public Command(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
}
}
================================================
FILE: appformer-js/.gitignore
================================================
node_modules/
dist/
coverage/
target/
================================================
FILE: appformer-js/README.md
================================================
Core
==
This package provides the public AppFormer.js API alongside with its Marshalling capabilities.
Usage
--
Imagine you have a ReactComponent
```typescript jsx
import * as React from "react";
class MyReactComponent extends React.Component<{ exposing: (self: MyReactComponent) => void }, {}> {
public fetchDataAndUpdate() {
//fetches some data and updates state
}
public render() {
return ...
;
}
}
```
Turning it into an `AppFormer.Screen` or `AppFormer.Perspective` is simple:
```typescript jsx
import * as React from "react";
import * as AppFormer from "appformer-js";
export class MyScreen extends AppFormer.Screen {
private screen: MyReactComponent;
constructor() {
super("my-screen");
this.af_isReact = true;
this.af_componentTitle = "MyScreen title";
}
af_onOpen(): void {
this.screen.fetchDataAndUpdate();
}
af_componentRoot(children?: any): AppFormer.Element {
return (this.screen = self)} />;
}
}
AppFormer.registerScreen(new MyScreen());
```
```typescript jsx
import * as React from "react";
import * as AppFormer from "appformer-js";
export class MyPerspective extends AppFormer.Perspective {
private perspective: MyReactComponent;
constructor() {
super("my-screen");
this.af_isReact = true;
}
af_onOpen(): void {
this.perspective.fetchDataAndUpdate();
}
af_componentRoot(children?: any): AppFormer.Element {
return (this.perspective = self)} />;
}
}
AppFormer.registerPerspective(new MyPerspective());
```
Note how AppFormer's lifecycle integrates with React's.
================================================
FILE: appformer-js/jest.config.js
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
module.exports = {
reporters: [
"default",
[
"jest-junit",
{
/*
* Removes spaces from test titles and makes first
* letter of each word capitalized.
*
* unit test -> UnitTest
*
* See junit.xml report for resulting look.
*/
titleTemplate: (vars) => {
var str = vars.title.toLowerCase();
str = str.split(' ');
for (var i = 0; i < str.length; i++) {
str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1);
}
var result = str.join('');
return result.replace(',');
}
}
]
],
moduleDirectories: ["node_modules", "src"],
moduleFileExtensions: ["js", "jsx", "ts", "tsx"],
testRegex: "/__tests__/.*\\.test\\.(jsx?|tsx?)$",
transform: {
"^.+\\.jsx?$": "babel-jest",
"^.+\\.tsx?$": "ts-jest"
}
};
================================================
FILE: appformer-js/package.json
================================================
{
"name": "appformer-js",
"version": "0.0.0",
"description": "",
"license": "Apache-2.0",
"main": "./dist/appformer.js",
"types": "./dist/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/kiegroup/appformer-js.git"
},
"dependencies": {
"@types/react": "16.14.5",
"@types/react-dom": "16.9.12",
"bignumber.js": "7.2.1",
"react": "16.14.0",
"react-dom": "16.14.0"
},
"scripts": {
"lint": "tslint -c tslint.json 'src/**/*.{ts,tsx,js,jsx}'",
"test": "jest",
"init": "yarn install --force",
"build": "yarn run lint && yarn test && webpack --mode production"
},
"babel": {
"presets": [
"env",
"react"
]
},
"jest-junit": {
"outputDirectory": "./target",
"suiteName": "org.appformer.js.tests",
"suiteNameTemplate": "{filename}",
"classNameTemplate": "org.appformer.js.tests.{filename}.{classname}"
},
"devDependencies": {
"@types/jest": "23.3.1",
"babel-core": "6.26.3",
"babel-jest": "23.0.0",
"babel-loader": "7.1.5",
"babel-preset-env": "1.7.0",
"babel-preset-react": "6.24.1",
"circular-dependency-plugin": "5.0.2",
"clean-webpack-plugin": "0.1.19",
"jest": "23.5.0",
"jest-junit": "6.3.0",
"prettier": "1.14.2",
"ts-jest": "23.1.3",
"ts-loader": "4.4.2",
"tslint": "5.11.0",
"tslint-config-prettier": "1.15.0",
"tslint-react": "3.6.0",
"typescript": "2.9.2",
"watch": "1.0.2",
"webpack": "4.15.1",
"webpack-cli": "3.0.8",
"write-file-atomic": "2.4.1"
},
"resolutions": {
"write-file-atomic": "2.4.1"
}
}
================================================
FILE: appformer-js/pom.xml
================================================
4.0.0
org.uberfire
uberfire-parent
7.75.0-SNAPSHOT
../pom.xml
jar
appformer-js
7.75.0-SNAPSHOT
AppFormer.js :: Core
AppFormer.js Core
com.github.eirslett
frontend-maven-plugin
${project.build.directory}
install yarn
install-node-and-yarn
install node and npm
initialize
install-node-and-npm
lock-treatment-tool execution
initialize
npm
exec @kie/lock-treatment-tool@${version.lock-treatment-tool} --
yarn run init
yarn
run init
yarn run build
yarn
run build
maven-resources-plugin
3.1.0
copy-resources
prepare-package
copy-resources
${project.build.outputDirectory}/META-INF/resources/webjars/${project.artifactId}/${project.version}/
dist/
false
.
package.json
================================================
FILE: appformer-js/prettier.config.js
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
module.exports = {
printWidth: 120
};
================================================
FILE: appformer-js/src/appformer/AppFormer.tsx
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import * as React from "react";
import { Element } from "../core";
import { Screen } from "./Screen";
import { Perspective } from "./Perspective";
import { Portable } from "../marshalling";
/**
* AppFormer.js public API.
*
*/
export class AppFormer {
/**
* Starts an AppFormer instance.
* @param container
* The DOM element on which AppFormer will start into
* @param callback
* Function to be executed after AppFormer init is complete
*/
public init(container: HTMLElement, callback: () => void): AppFormer {
return this;
}
/**
* Registers a Screen component.
* @param screen
*/
// tslint:disable-next-line
public registerScreen(screen: Screen): void {}
/**
* Registers a Perspective component
* @param perspective
*/
// tslint:disable-next-line
public registerPerspective(perspective: Perspective): void {}
/**
* Renders the component with the corresponding id.
* @param af_componentId
* The component id
* @param args
* Arbitrary arguments to be used by the component
*/
// tslint:disable-next-line
public goTo(af_componentId: string, args?: Map): void {}
/**
* Translates a bundle key
* @param tkey
* The bundle key
* @param args
* The arguments to this bundle
*/
// tslint:disable-next-line
public translate(tkey: string, args: string[]): string {
throw new Error("Not implemented");
}
/**
* Renders a component.
* @param element
* The component to be rendered
* @param container
* The DOM element on which the component will be rendered.
* @param callback
* Function to be executed after the component is done rendering.
*/
// tslint:disable-next-line
public render(element: Element, container: HTMLElement, callback: () => void): void {}
/**
* Fires an event using Errai bus.
* @param obj
* The event object.
*/
// tslint:disable-next-line
public fireEvent(obj: Portable): void {}
/**
* Executes an RPC call to an Errai Remote.
* @param path
* The Errai bus RPC path
* @param args
* The arguments to this RPC
*/
public rpc(path: string, args: Array>): Promise {
throw new Error("Not implemented");
}
/**
* Unrenders a component
* @param af_componentId
* The component id.
*/
// tslint:disable-next-line
public close(af_componentId: string): void {}
}
================================================
FILE: appformer-js/src/appformer/CompassLayoutPerspective.tsx
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import * as React from "react";
import { Perspective } from "./Perspective";
import { Menu, Toolbar } from "./Components";
import { Panel, PanelType } from "./Panel";
import { DisplayInfo } from "./DisplayInfo";
import { Part } from "./Part";
import { Element } from "../core";
/**
* Special type of Perspective. It allows its UI to be defined by parts and panels.
*/
export class CompassLayoutPerspective extends Perspective {
private _af_menus?: Menu[] = undefined;
private _af_toolbar?: Toolbar = undefined;
private _af_defaultPanelType: PanelType = PanelType.MULTI_LIST;
private _af_displayInfo: DisplayInfo = new DisplayInfo();
private _af_parts: Part[] = [];
private _af_panels: Panel[] = [];
protected constructor(componentId: string) {
super(componentId);
this.af_isTemplated = false;
}
public af_componentRoot(children?: any): Element {
// TODO: translate compass layout to a templated component
return
;
}
get af_menus(): Menu[] | undefined {
return this._af_menus;
}
set af_menus(value: Menu[] | undefined) {
this._af_menus = value;
}
get af_toolbar(): Toolbar | undefined {
return this._af_toolbar;
}
set af_toolbar(value: Toolbar | undefined) {
this._af_toolbar = value;
}
get af_defaultPanelType(): PanelType {
return this._af_defaultPanelType;
}
set af_defaultPanelType(value: PanelType) {
this._af_defaultPanelType = value;
}
get af_displayInfo(): DisplayInfo {
return this._af_displayInfo;
}
set af_displayInfo(value: DisplayInfo) {
this._af_displayInfo = value;
}
get af_parts(): Part[] {
return this._af_parts;
}
set af_parts(value: Part[]) {
this._af_parts = value;
}
get af_panels(): Panel[] {
return this._af_panels;
}
set af_panels(value: Panel[]) {
this._af_panels = value;
}
}
================================================
FILE: appformer-js/src/appformer/Component.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Component as CoreComponent } from "../core";
import { Element } from "../core";
/**
* Base AppFormer.js component. It contains the default life-cycle methods that are common to all components.
*
*/
export abstract class Component extends CoreComponent {
public readonly af_componentId: string;
public af_subscriptions: Map void)> = new Map();
protected constructor(args: { type: string; af_componentId: string }) {
super({ type: args.type, core_componentId: args.af_componentId });
this.af_componentId = args.af_componentId;
}
public af_onStartup(): void {
//
}
public af_onOpen(): void {
//
}
public af_onFocus(): void {
//
}
public af_onLostFocus(): void {
//
}
public af_onMayClose(): boolean {
return true;
}
public af_onClose(): void {
//
}
public af_onShutdown(): void {
//
}
public core_componentRoot(children?: any): Element {
return this.af_componentRoot(children);
}
public abstract af_componentRoot(children?: any): Element;
}
================================================
FILE: appformer-js/src/appformer/ComponentTypes.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export enum ComponentTypes {
SCREEN = "screen",
PERSPECTIVE = "perspective",
APPFORMER = "appformer",
EDITOR = "editor"
}
================================================
FILE: appformer-js/src/appformer/Components.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export const DefaultComponentContainerId = "af-js-default-screen-container";
export class Menu {
// TODO
}
export class Toolbar {
// TODO
}
================================================
FILE: appformer-js/src/appformer/DisplayInfo.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export class DisplayInfo {
private _contextId?: string = undefined;
private _contextDisplayMode: ContextDisplayMode = ContextDisplayMode.SHOW;
get contextId(): string | undefined {
return this._contextId;
}
set contextId(value: string | undefined) {
this._contextId = value;
}
get contextDisplayMode(): ContextDisplayMode {
return this._contextDisplayMode;
}
set contextDisplayMode(value: ContextDisplayMode) {
this._contextDisplayMode = value;
}
}
export enum ContextDisplayMode {
SHOW = "SHOW",
HIDE = "HIDE"
}
================================================
FILE: appformer-js/src/appformer/Panel.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Part } from "./Part";
import { DisplayInfo } from "./DisplayInfo";
export enum PanelType {
MULTI_LIST = "org.uberfire.client.workbench.panels.impl.MultiListWorkbenchPanelPresenter",
STATIC = "org.uberfire.client.workbench.panels.impl.StaticWorkbenchPanelPresenter"
}
export enum CompassPosition {
NONE = "NONE",
NORTH = "NORTH",
SOUTH = "SOUTH",
EAST = "EAST",
WEST = "WEST",
SELF = "SELF",
ROOT = "ROOT",
CENTER = "CENTER"
}
/**
* Panel of a CompassLayoutPerspective
*/
export class Panel {
private _position: CompassPosition;
private _width: number = -1;
private _minWidth: number = -1;
private _height: number = -1;
private _minHeight: number = -1;
private _children: Panel[] = [];
private _parts: Part[] = [];
private _panelType: PanelType = PanelType.MULTI_LIST;
private _displayInfo: DisplayInfo = new DisplayInfo();
constructor(position: CompassPosition) {
this._position = position;
}
get position(): CompassPosition {
return this._position;
}
set position(value: CompassPosition) {
this._position = value;
}
get width(): number {
return this._width;
}
set width(value: number) {
this._width = value;
}
get minWidth(): number {
return this._minWidth;
}
set minWidth(value: number) {
this._minWidth = value;
}
get height(): number {
return this._height;
}
set height(value: number) {
this._height = value;
}
get minHeight(): number {
return this._minHeight;
}
set minHeight(value: number) {
this._minHeight = value;
}
get children(): Panel[] {
return this._children;
}
set children(value: Panel[]) {
this._children = value;
}
get parts(): Part[] {
return this._parts;
}
set parts(value: Part[]) {
this._parts = value;
}
get panelType(): PanelType {
return this._panelType;
}
set panelType(value: PanelType) {
this._panelType = value;
}
get displayInfo(): DisplayInfo {
return this._displayInfo;
}
set displayInfo(value: DisplayInfo) {
this._displayInfo = value;
}
}
================================================
FILE: appformer-js/src/appformer/Part.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { DisplayInfo } from "./DisplayInfo";
/**
* Part of a CompassLayoutPerspective
*/
export class Part {
private _placeName: string;
private _displayInfo: DisplayInfo = new DisplayInfo();
private _parameters: {} = {};
constructor(placeName: string) {
this._placeName = placeName;
}
get placeName(): string {
return this._placeName;
}
set placeName(value: string) {
this._placeName = value;
}
get displayInfo(): DisplayInfo {
return this._displayInfo;
}
set displayInfo(value: DisplayInfo) {
this._displayInfo = value;
}
get parameters(): {} {
return this._parameters;
}
set parameters(value: {}) {
this._parameters = value;
}
}
================================================
FILE: appformer-js/src/appformer/Perspective.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Component } from "./Component";
/**
* Perspective component API. Implement this class to create a Perspective.
*/
export abstract class Perspective extends Component {
public af_name: string;
public af_perspectiveScreens: string[] = [];
public af_isDefault: boolean = false;
public af_isTransient: boolean = true;
public af_isTemplated: boolean = true;
protected constructor(componentId: string) {
super({ type: "perspective", af_componentId: componentId });
}
public af_onStartup(): void {
//
}
public af_onOpen(): void {
//
}
public af_onClose(): void {
//
}
public af_onShutdown(): void {
//
}
}
================================================
FILE: appformer-js/src/appformer/Screen.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Component } from "./Component";
/**
* Screen component API. Implement this class to create a Screen.
*/
export abstract class Screen extends Component {
public af_componentTitle?: string = undefined;
public af_subscriptions: Map void)> = new Map();
protected constructor(componentId: string) {
super({ type: "screen", af_componentId: componentId });
}
public af_onStartup(): void {
//
}
public af_onOpen(): void {
//
}
public af_onFocus(): void {
//
}
public af_onLostFocus(): void {
//
}
public af_onMayClose(): boolean {
return true;
}
public af_onClose(): void {
//
}
public af_onShutdown(): void {
//
}
}
================================================
FILE: appformer-js/src/appformer/index.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { AppFormer } from "./AppFormer";
import { Element } from "../core";
import { findChildContainers } from "../util";
import { Component } from "./Component";
import { Perspective } from "./Perspective";
import { Screen } from "./Screen";
import {marshall, Portable} from "../marshalling";
export * from "./AppFormer";
export * from "./Components";
export * from "./Screen";
export * from "./ComponentTypes";
export * from "./Perspective";
export * from "./CompassLayoutPerspective";
export * from "./DisplayInfo";
export * from "./Panel";
export * from "./Part";
let singleton: AppFormer | undefined;
export function initSingleton() {
const $wnd = window as any;
if ($wnd.AppFormerMode !== "instance") {
singleton =
$wnd.appformerGwtBridge ||
new AppFormer().init((document.body.children[0] as HTMLElement) || document.createElement("div"), () => {
// creating div element is used in test environment, when test runner do not have a page body to access
console.info("AppFormer _standalone_ instance initialized.");
});
$wnd.AppFormerInstance = singleton;
}
}
//
//Singleton API
export function register(component: Component) {
if (component.type === "screen") {
singleton!.registerScreen(component as Screen);
} else if (component.type === "perspective") {
singleton!.registerPerspective(component as Perspective);
}
}
export function goTo(af_componentId: string) {
singleton!.goTo(af_componentId);
}
export function close(af_componentId: string) {
singleton!.close(af_componentId);
}
export function translate(key: string, args: string[]) {
return singleton!.translate(key, args);
}
export function render(element: Element, container: HTMLElement, callback = (): void => undefined) {
singleton!.render(element, container, callback);
}
export function fireEvent(obj: Portable) {
singleton!.fireEvent(marshall(obj) as any);
}
export function rpc(path: string, args: Array>) {
return singleton!.rpc(path, args);
}
(window as any)._AppFormerUtils = {
findChildContainers
};
================================================
FILE: appformer-js/src/core/Component.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import * as React from "react";
/**
* Core component. Provides basic low-level lifecycle methods for AppFormer components.
*/
export abstract class Component {
public readonly core_componentId: string;
public readonly type: string;
public readonly _container: HTMLElement;
public readonly _components: string[] = [];
public af_isReact: boolean = false;
public af_hasContext: boolean = false;
protected constructor(args: { type: string; core_componentId: string }) {
this.core_componentId = args.core_componentId;
this.type = args.type;
}
public abstract core_componentRoot(children?: any): Element;
public core_onReady() {
console.info(`core: ${this.core_componentId} is ready.`);
}
public core_onVanished() {
console.info(`core: ${this.core_componentId} was removed.`);
}
}
export type Element = React.ReactPortal | React.ReactElement | HTMLElement | string;
================================================
FILE: appformer-js/src/core/index.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export { Component, Element } from "./Component";
================================================
FILE: appformer-js/src/index.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { initSingleton } from "./appformer";
export * from "./appformer";
export * from "./marshalling";
export * from "./core";
export * from "./java-wrappers";
export * from "./util";
// Exposes this module as a global variable
(window as any).AppFormer = this;
initSingleton();
================================================
FILE: appformer-js/src/java-wrappers/BigNumberWrapper.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { BigNumber } from "bignumber.js";
import { JavaWrapper } from "./JavaWrapper";
export abstract class BigNumberWrapper extends JavaWrapper {
private _value: BigNumber;
public constructor(value: string) {
super();
const valueAsNumber = this.from(value);
this.set(valueAsNumber);
}
public get(): BigNumber {
return this._value;
}
public set(value: BigNumber | ((current: BigNumber) => BigNumber)): void {
if (this.instanceOfBigNumber(value)) {
this._value = this.applyNumericRange(value);
} else {
this._value = this.applyNumericRange(value(this.get()));
}
}
protected abstract from(asString: string): BigNumber;
protected abstract isInRange(n: BigNumber): boolean;
private applyNumericRange(value: BigNumber) {
if (!this.isInRange(value)) {
return new BigNumber(NaN);
}
return value;
}
private instanceOfBigNumber(value: any): value is BigNumber {
return BigNumber.isBigNumber(value);
}
}
================================================
FILE: appformer-js/src/java-wrappers/FloatBasedJavaNumber.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NumberWrapper } from "./NumberWrapper";
export abstract class FloatBasedJavaNumber extends NumberWrapper {
protected from(asString: string): number {
return Number.parseFloat(asString);
}
}
================================================
FILE: appformer-js/src/java-wrappers/IntegerBasedJavaNumber.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NumberWrapper } from "./NumberWrapper";
export abstract class IntegerBasedJavaNumber extends NumberWrapper {
protected from(asString: string): number {
return Number.parseInt(asString, 10);
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaArrayList.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaCollection } from "./JavaCollection";
import { instanceOfArray } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaArrayList extends JavaCollection {
private readonly _fqcn = JavaType.ARRAY_LIST;
private _value: T[];
constructor(value: T[]) {
super();
this.set(value);
}
public get(): T[] {
return this._value;
}
public set(val: ((current: T[]) => T[]) | T[]): void {
if (instanceOfArray(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaBigDecimal.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { BigNumber } from "bignumber.js";
import { BigNumberWrapper } from "./BigNumberWrapper";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaBigDecimal extends BigNumberWrapper implements JavaNumber {
private readonly _fqcn = JavaType.BIG_DECIMAL;
public from(asString: string): BigNumber {
return new BigNumber(asString, 10);
}
public isInRange(n: BigNumber): boolean {
return true; // arbitrary precision
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaBigInteger.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { BigNumber } from "bignumber.js";
import { BigNumberWrapper } from "./BigNumberWrapper";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaBigInteger extends BigNumberWrapper implements JavaNumber {
private readonly _fqcn = JavaType.BIG_INTEGER;
public from(asString: string): BigNumber {
const bigNumber = new BigNumber(asString, 10);
if (bigNumber.isInteger()) {
return bigNumber;
}
// truncates decimal part (like TS's Number type)
return bigNumber.integerValue(BigNumber.ROUND_DOWN);
}
protected isInRange(n: BigNumber): boolean {
return true; // arbitrary precision
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaBoolean.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { instanceOfBoolean } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaBoolean extends JavaWrapper {
private readonly _fqcn = JavaType.BOOLEAN;
private _value: boolean;
constructor(value: boolean) {
super();
this.set(value);
}
public get(): boolean {
return this._value;
}
public set(val: ((current: boolean) => boolean) | boolean): void {
if (instanceOfBoolean(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaByte.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { IntegerBasedJavaNumber } from "./IntegerBasedJavaNumber";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaByte extends IntegerBasedJavaNumber implements JavaNumber {
public static readonly MIN_VALUE = -128;
public static readonly MAX_VALUE = 127;
private readonly _fqcn = JavaType.BYTE;
protected isInRange(n: number): boolean {
return n >= JavaByte.MIN_VALUE && n <= JavaByte.MAX_VALUE;
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaCollection.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
export abstract class JavaCollection | null> extends JavaWrapper {
// this is here for type purposes only
}
================================================
FILE: appformer-js/src/java-wrappers/JavaDate.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { instanceOfDate } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaDate extends JavaWrapper {
private readonly _fqcn = JavaType.DATE;
private _value: Date;
constructor(date: Date) {
super();
this.set(date);
}
public get(): Date {
return this._value;
}
public set(val: ((current: Date) => Date) | Date): void {
if (instanceOfDate(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaDouble.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { FloatBasedJavaNumber } from "./FloatBasedJavaNumber";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaDouble extends FloatBasedJavaNumber implements JavaNumber {
private readonly _fqcn = JavaType.DOUBLE;
protected isInRange(n: number): boolean {
// JS' numbers are 64 bits long like Java's Double
return n >= -1 * Number.MAX_VALUE && n <= Number.MAX_VALUE;
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaEnum.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Portable } from "../marshalling";
export abstract class JavaEnum> implements Portable {
public readonly name: string;
protected constructor(name: string) {
this.name = name;
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaFloat.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { FloatBasedJavaNumber } from "./FloatBasedJavaNumber";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaFloat extends FloatBasedJavaNumber implements JavaNumber {
public static readonly MIN_VALUE = -3.40282347e38;
public static readonly MAX_VALUE = 3.40282347e38;
private readonly _fqcn = JavaType.FLOAT;
protected isInRange(n: number): boolean {
return n >= JavaFloat.MIN_VALUE && n <= JavaFloat.MAX_VALUE;
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaHashMap.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { instanceOfMap } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaHashMap extends JavaWrapper> {
private readonly _fqcn = JavaType.HASH_MAP;
private _value: Map;
constructor(value: Map) {
super();
this.set(value);
}
public get(): Map {
return this._value;
}
public set(val: ((current: Map) => Map) | Map): void {
if (instanceOfMap(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaHashSet.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaCollection } from "./JavaCollection";
import { instanceOfSet } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaHashSet extends JavaCollection> {
private readonly _fqcn = JavaType.HASH_SET;
private _value: Set;
constructor(value: Set) {
super();
this.set(value);
}
public get(): Set {
return this._value;
}
public set(val: ((current: Set) => Set) | Set): void {
if (instanceOfSet(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaInteger.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { IntegerBasedJavaNumber } from "./IntegerBasedJavaNumber";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaShort } from "./JavaShort";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaInteger extends IntegerBasedJavaNumber implements JavaNumber {
public static readonly MIN_VALUE = -21474836488;
public static readonly MAX_VALUE = 2147483647;
private readonly _fqcn = JavaType.INTEGER;
protected isInRange(n: number): boolean {
return n >= JavaInteger.MIN_VALUE && n <= JavaInteger.MAX_VALUE;
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaLinkedList.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export class JavaLinkedList {}
================================================
FILE: appformer-js/src/java-wrappers/JavaLong.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { BigNumber } from "bignumber.js";
import { BigNumberWrapper } from "./BigNumberWrapper";
import { JavaByte } from "./JavaByte";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaType } from "./JavaType";
export class JavaLong extends BigNumberWrapper implements JavaNumber {
public static readonly MIN_VALUE = new BigNumber("-9223372036854775808", 10);
public static readonly MAX_VALUE = new BigNumber("9223372036854775807", 10);
private readonly _fqcn = JavaType.LONG;
public from(asString: string): BigNumber {
// simulate Java's Long number range
const BN = BigNumber.clone({ RANGE: 18, DECIMAL_PLACES: 0 });
// forces integer value (the decimal places configuration are only applied when performing a division)
// Also, truncates the decimal part the same way of Number type
return new BN(asString).integerValue(BigNumber.ROUND_DOWN);
}
protected isInRange(n: BigNumber): boolean {
return n.isGreaterThanOrEqualTo(JavaLong.MIN_VALUE) && n.isLessThanOrEqualTo(JavaLong.MAX_VALUE);
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaNumber.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaDouble } from "./JavaDouble";
import { JavaInteger } from "./JavaInteger";
import { JavaShort } from "./JavaShort";
import { JavaByte } from "./JavaByte";
import { JavaFloat } from "./JavaFloat";
import { BigNumber } from "bignumber.js";
import { JavaLong } from "./JavaLong";
export interface JavaNumber {
doubleValue(): JavaDouble;
intValue(): JavaInteger;
shortValue(): JavaShort;
byteValue(): JavaByte;
floatValue(): JavaFloat;
longValue(): JavaLong;
}
export function asDouble(n: number | BigNumber) {
return new JavaDouble(n.toString(10));
}
export function asInteger(n: number | BigNumber) {
return new JavaInteger(n.toString(10));
}
export function asShort(n: number | BigNumber) {
return new JavaShort(n.toString(10));
}
export function asByte(n: number | BigNumber) {
return new JavaByte(n.toString(10));
}
export function asFloat(n: number | BigNumber) {
return new JavaFloat(n.toString(10));
}
export function asLong(n: number | BigNumber) {
return new JavaLong(n.toString(10));
}
================================================
FILE: appformer-js/src/java-wrappers/JavaOptional.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { JavaType } from "./JavaType";
export class JavaOptional extends JavaWrapper {
private readonly _fqcn = JavaType.OPTIONAL;
private _value: T | undefined;
constructor(value?: T) {
super();
this.set(value);
}
public get(): T {
if (this._value === null || this._value === undefined) {
throw new Error("No value present");
}
return this._value!;
}
public isPresent(): boolean {
return this._value !== undefined;
}
public set(val: ((current: T | undefined) => T | undefined) | T | undefined): void {
if (typeof val === "function") {
this._value = val(this.get());
} else {
this._value = val;
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaShort.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { IntegerBasedJavaNumber } from "./IntegerBasedJavaNumber";
import { asByte, asDouble, asFloat, asInteger, asLong, asShort, JavaNumber } from "./JavaNumber";
import { JavaByte } from "./JavaByte";
import { JavaDouble } from "./JavaDouble";
import { JavaFloat } from "./JavaFloat";
import { JavaInteger } from "./JavaInteger";
import { JavaLong } from "./JavaLong";
import { JavaType } from "./JavaType";
export class JavaShort extends IntegerBasedJavaNumber implements JavaNumber {
public static readonly MIN_VALUE = -32768;
public static readonly MAX_VALUE = 32767;
private readonly _fqcn = JavaType.SHORT;
protected isInRange(n: number): boolean {
return n >= JavaShort.MIN_VALUE && n <= JavaShort.MAX_VALUE;
}
public byteValue(): JavaByte {
return asByte(super.get());
}
public doubleValue(): JavaDouble {
return asDouble(super.get());
}
public floatValue(): JavaFloat {
return asFloat(super.get());
}
public intValue(): JavaInteger {
return asInteger(super.get());
}
public shortValue(): JavaShort {
return asShort(super.get());
}
public longValue(): JavaLong {
return asLong(super.get());
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaString.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { instanceOfString } from "../util/TypeUtils";
import { JavaType } from "./JavaType";
export class JavaString extends JavaWrapper {
private readonly _fqcn = JavaType.STRING;
private _value: string;
constructor(value: string) {
super();
this.set(value);
}
public get(): string {
return this._value;
}
public set(val: ((current: string) => string) | string): void {
if (instanceOfString(val)) {
this._value = val;
} else {
this._value = val(this.get());
}
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaTreeMap.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export class JavaTreeMap {}
================================================
FILE: appformer-js/src/java-wrappers/JavaTreeSet.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export class JavaTreeSet {}
================================================
FILE: appformer-js/src/java-wrappers/JavaType.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export enum JavaType {
BYTE = "java.lang.Byte",
DOUBLE = "java.lang.Double",
FLOAT = "java.lang.Float",
INTEGER = "java.lang.Integer",
LONG = "java.lang.Long",
SHORT = "java.lang.Short",
BOOLEAN = "java.lang.Boolean",
STRING = "java.lang.String",
DATE = "java.util.Date",
BIG_DECIMAL = "java.math.BigDecimal",
BIG_INTEGER = "java.math.BigInteger",
ARRAY_LIST = "java.util.ArrayList",
UNMODIFIABLE_COLLECTION = "java.util.Collections$UnmodifiableCollection",
UNMODIFIABLE_SET = "java.util.Collections$UnmodifiableSet",
UNMODIFIABLE_MAP = "java.util.Collections$UnmodifiableMap",
HASH_SET = "java.util.HashSet",
HASH_MAP = "java.util.HashMap",
OPTIONAL = "java.util.Optional",
ENUM = "java.lang.Enum"
}
================================================
FILE: appformer-js/src/java-wrappers/JavaWrapper.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Portable } from "../marshalling/Portable";
export abstract class JavaWrapper implements Portable> {
private static readonly javaWrapperInstanceIdentifier = "fbeef485-6129-4c23-a047-166c6d2fb7a9";
public abstract get(): T;
public abstract set(val: T | ((current: T) => T)): void;
private instanceIdentifier(): string {
return JavaWrapper.javaWrapperInstanceIdentifier;
}
public static extendsJavaWrapper(obj: any): obj is JavaWrapper {
if (!obj.instanceIdentifier) {
return false;
}
// this is just a trick to allow the application to identify in runtime if an object extends JavaWrapper.
return obj.instanceIdentifier() === JavaWrapper.javaWrapperInstanceIdentifier;
}
}
================================================
FILE: appformer-js/src/java-wrappers/JavaWrapperUtils.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
import { JavaType } from "./JavaType";
import { isArray, isBoolean, isDate, isMap, isSet, isString } from "../util/TypeUtils";
import { JavaArrayList } from "./JavaArrayList";
import { JavaHashSet } from "./JavaHashSet";
import { JavaHashMap } from "./JavaHashMap";
import { JavaBoolean } from "./JavaBoolean";
import { JavaString } from "./JavaString";
import { JavaDate } from "./JavaDate";
import { JavaEnum } from "./JavaEnum";
export class JavaWrapperUtils {
private static wrappingFuncForType: Map<(obj: any) => boolean, (obj: any) => JavaWrapper> = new Map([
[isArray, (obj: any) => new JavaArrayList(obj) as JavaWrapper],
[isSet, (obj: any) => new JavaHashSet(obj) as JavaWrapper],
[isMap, (obj: any) => new JavaHashMap(obj) as JavaWrapper],
[isBoolean, (obj: any) => new JavaBoolean(obj) as JavaWrapper],
[isString, (obj: any) => new JavaString(obj) as JavaWrapper],
[isDate, (obj: any) => new JavaDate(obj) as JavaWrapper]
]);
public static needsWrapping(obj: any): boolean {
return this.getWrappingFunction(obj) !== undefined;
}
public static wrapIfNeeded(obj: U): JavaWrapper | U {
const func = this.getWrappingFunction(obj);
if (!func) {
return obj;
}
return func(obj);
}
public static isJavaType(fqcn: string): boolean {
for (const type in JavaType) {
if (JavaType[type] === fqcn) {
return true;
}
}
return false;
}
public static isEnum(obj: any): boolean {
return obj instanceof JavaEnum;
}
private static getWrappingFunction(obj: any): ((obj: any) => JavaWrapper) | undefined {
//tslint:disable-next-line
let result: ((obj: any) => JavaWrapper) | undefined = undefined;
this.wrappingFuncForType.forEach((wrapFunction, typeFilterFunction) => {
if (result) {
return;
}
if (typeFilterFunction(obj)) {
result = wrapFunction;
}
});
return result;
}
}
================================================
FILE: appformer-js/src/java-wrappers/NumberWrapper.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "./JavaWrapper";
export abstract class NumberWrapper extends JavaWrapper {
private _value: number;
public constructor(value: string) {
super();
const valueAsNumber = this.from(value);
this.set(valueAsNumber);
}
public get(): number {
return this._value;
}
public set(value: number | ((current: number) => number)): void {
if (typeof value === "number") {
this._value = this.applyNumericRange(value);
} else {
this._value = this.applyNumericRange(value(this.get()));
}
}
protected abstract from(asString: string): number;
protected abstract isInRange(n: number): boolean;
private applyNumericRange(n: number): number {
if (!this.isInRange(n)) {
return Number.NaN;
}
return n;
}
}
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaArrayList.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaArrayList } from "../JavaArrayList";
import { JavaType } from "../JavaType";
describe("get", () => {
test("with populated array, returns the same array", () => {
const input = ["foo", "bar", "foo2"];
const output = new JavaArrayList(input).get();
expect(output).toEqual(["foo", "bar", "foo2"]);
});
test("with empty array, returns the same array", () => {
const input = [] as any[];
const output = new JavaArrayList(input).get();
expect(output).toEqual([]);
});
});
describe("set", () => {
test("with direct value, should set", () => {
const input = new JavaArrayList(["foo", "bar"]);
expect(input.get()).toStrictEqual(["foo", "bar"]);
input.set(["foo"]);
expect(input.get()).toStrictEqual(["foo"]);
});
test("with value from function, should set", () => {
const input = new JavaArrayList(["foo", "bar"]);
expect(input.get()).toStrictEqual(["foo", "bar"]);
input.set(curr => {
const newArr = new Array(...curr);
newArr.push("newfoo");
return newArr;
});
expect(input.get()).toStrictEqual(["foo", "bar", "newfoo"]);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaArrayList(["1", "2"]) as any)._fqcn;
expect(fqcn).toBe(JavaType.ARRAY_LIST);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaBigDecimal.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaBigDecimal } from "../JavaBigDecimal";
import { BigNumber } from "bignumber.js";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive float, should return same value as BigNumber", () => {
const input = "12.92";
const output = new JavaBigDecimal(input).get();
expect(output).toEqual(new BigNumber("12.92"));
});
test("negative float, should return same value as BigNumber", () => {
const input = "-12.92";
const output = new JavaBigDecimal(input).get();
expect(output).toEqual(new BigNumber("-12.92"));
});
test("positive integer, should return same value as BigNumber", () => {
const input = "12";
const output = new JavaBigDecimal(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("negative integer, should return same value as BigNumber", () => {
const input = "-12";
const output = new JavaBigDecimal(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaBigDecimal(input).get();
expect(output).toEqual(new BigNumber(NaN));
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = new BigNumber(-Number.MAX_VALUE);
const output = new JavaBigDecimal(input.toString(10)).get();
expect(output).toEqual(new BigNumber(-Number.MAX_VALUE));
});
test("less than, should return same value as BigNumber", () => {
const input = new BigNumber(-Number.MAX_VALUE).minus(1, 10);
const output = new JavaBigDecimal(input.toString(10)).get();
expect(output).toEqual(new BigNumber(-Number.MAX_VALUE).minus(1, 10));
});
});
describe("maximum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = new BigNumber(Number.MAX_VALUE);
const output = new JavaBigDecimal(input.toString(10)).get();
expect(output).toEqual(new BigNumber(Number.MAX_VALUE));
});
test("greater than, should return same value as BigNumber", () => {
const input = new BigNumber(Number.MAX_VALUE).plus(1, 10);
const output = new JavaBigDecimal(input.toString(10)).get();
expect(output).toEqual(new BigNumber(Number.MAX_VALUE).plus(1, 10));
});
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaBigDecimal("1.2");
expect(input.get()).toEqual(new BigNumber("1.2"));
input.set(new BigNumber("2.2"));
expect(input.get()).toEqual(new BigNumber("2.2"));
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaBigDecimal("1.2");
expect(input.get()).toEqual(new BigNumber("1.2"));
input.set(new BigNumber(NaN));
expect(input.get()).toEqual(new BigNumber(NaN));
});
test("with valid value from function, should set", () => {
const input = new JavaBigDecimal("1.2");
expect(input.get()).toEqual(new BigNumber("1.2"));
input.set(cur => new BigNumber("2.2").plus(cur));
expect(input.get()).toEqual(new BigNumber("3.4"));
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaBigDecimal("1.2");
expect(input.get()).toEqual(new BigNumber("1.2"));
input.set(cur => new BigNumber(NaN).plus(cur));
expect(input.get()).toEqual(new BigNumber(NaN));
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1.2");
const output = input.doubleValue();
expect(output.get()).toBe(1.2);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1.1");
const output = input.floatValue();
expect(output.get()).toBe(1.1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaBigDecimal("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaBigDecimal("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.BIG_DECIMAL);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaBigInteger.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { BigNumber } from "bignumber.js";
import { JavaBigInteger } from "../JavaBigInteger";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive integer, should return same value as BigNumber", () => {
const input = "12";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("negative integer, should return same value as BigNumber", () => {
const input = "-12";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber(NaN));
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = new BigNumber(-Number.MAX_VALUE);
const output = new JavaBigInteger(input.toString(10)).get();
expect(output).toEqual(new BigNumber(-Number.MAX_VALUE));
});
test("less than, should return same value as BigNumber", () => {
const input = new BigNumber(-Number.MAX_VALUE).minus(1, 10);
const output = new JavaBigInteger(input.toString(10)).get();
expect(output).toEqual(new BigNumber(-Number.MAX_VALUE).minus(1, 10));
});
});
describe("maximum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = new BigNumber(Number.MAX_VALUE);
const output = new JavaBigInteger(input.toString(10)).get();
expect(output).toEqual(new BigNumber(Number.MAX_VALUE));
});
test("greater than, should return same value as BigNumber", () => {
const input = new BigNumber(Number.MAX_VALUE).plus(1, 10);
const output = new JavaBigInteger(input.toString(10)).get();
expect(output).toEqual(new BigNumber(Number.MAX_VALUE).plus(1, 10));
});
});
});
describe("with float string", () => {
test("positive with decimal closest to 0, should return truncated value as BigNumber", () => {
const input = "12.1";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("positive with decimal exactly between 0 and 1, should return truncated value as BigNumber", () => {
const input = "12.5";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("positive with decimal closest to 1, should return truncated value as BigNumber", () => {
const input = "12.9";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("negative with decimal closest to 0, should return truncated value as BigNumber", () => {
const input = "-12.1";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
test("negative with decimal exactly between 0 and 1, should return truncated value as BigNumber", () => {
const input = "-12.5";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
test("negative with decimal closest to 1, should return truncated value as BigNumber", () => {
const input = "-12.9";
const output = new JavaBigInteger(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaBigInteger("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(new BigNumber("2"));
expect(input.get()).toEqual(new BigNumber("2"));
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaBigInteger("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(new BigNumber(NaN));
expect(input.get()).toEqual(new BigNumber(NaN));
});
test("with valid value from function, should set", () => {
const input = new JavaBigInteger("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(cur => new BigNumber("2").plus(cur));
expect(input.get()).toEqual(new BigNumber("3"));
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaBigInteger("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(cur => new BigNumber(NaN).plus(cur));
expect(input.get()).toEqual(new BigNumber(NaN));
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.doubleValue();
expect(output.get()).toBe(1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.floatValue();
expect(output.get()).toBe(1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaBigInteger("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaBigInteger("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.BIG_INTEGER);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaBoolean.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaBoolean } from "../JavaBoolean";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("true, should return boolean true", () => {
const input = true;
const output = new JavaBoolean(input).get();
expect(output).toBeTruthy();
});
test("false, should return boolean false", () => {
const input = false;
const output = new JavaBoolean(input).get();
expect(output).toBeFalsy();
});
});
});
describe("set", () => {
test("with direct value, should set", () => {
const input = new JavaBoolean(false);
expect(input.get()).toBeFalsy();
input.set(true);
expect(input.get()).toBeTruthy();
});
test("with value from function, should set", () => {
const input = new JavaBoolean(false);
expect(input.get()).toBeFalsy();
input.set(cur => !cur);
expect(input.get()).toBeTruthy();
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaBoolean(true) as any)._fqcn;
expect(fqcn).toBe(JavaType.BOOLEAN);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaByte.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaByte } from "../JavaByte";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive integer, should return same value as number", () => {
const input = "12";
const output = new JavaByte(input).get();
expect(output).toEqual(12);
});
test("negative integer, should return same value as number", () => {
const input = "-12";
const output = new JavaByte(input).get();
expect(output).toEqual(-12);
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaByte(input).get();
expect(output).toBeNaN();
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaByte.MIN_VALUE}`;
const output = new JavaByte(input).get();
expect(output).toEqual(JavaByte.MIN_VALUE);
});
test("less than, should return NaN", () => {
const input = `${JavaByte.MIN_VALUE - 1}`;
const output = new JavaByte(input).get();
expect(output).toEqual(NaN);
});
});
describe("maximum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaByte.MAX_VALUE}`;
const output = new JavaByte(input).get();
expect(output).toEqual(JavaByte.MAX_VALUE);
});
test("greater than, should return NaN", () => {
const input = `${JavaByte.MAX_VALUE + 1}`;
const output = new JavaByte(input).get();
expect(output).toEqual(NaN);
});
});
});
describe("with float string", () => {
test("positive with decimal closest to 0, should return truncated value as Number", () => {
const input = "12.1";
const output = new JavaByte(input).get();
expect(output).toEqual(12);
});
test("positive with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "12.5";
const output = new JavaByte(input).get();
expect(output).toEqual(12);
});
test("positive with decimal closest to 1, should return truncated value as Number", () => {
const input = "12.9";
const output = new JavaByte(input).get();
expect(output).toEqual(12);
});
test("negative with decimal closest to 0, should return truncated value as Number", () => {
const input = "-12.1";
const output = new JavaByte(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "-12.5";
const output = new JavaByte(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal closest to 1, should return truncated value as Number", () => {
const input = "-12.9";
const output = new JavaByte(input).get();
expect(output).toEqual(-12);
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaByte("1");
expect(input.get()).toEqual(1);
input.set(2);
expect(input.get()).toEqual(2);
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaByte("1");
expect(input.get()).toEqual(1);
input.set(JavaByte.MAX_VALUE + 1);
expect(input.get()).toEqual(NaN);
});
test("with valid value from function, should set", () => {
const input = new JavaByte("1");
expect(input.get()).toEqual(1);
input.set(cur => 2 + cur);
expect(input.get()).toEqual(3);
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaByte("1");
expect(input.get()).toEqual(1);
input.set(cur => JavaByte.MAX_VALUE + cur);
expect(input.get()).toEqual(NaN);
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.doubleValue();
expect(output.get()).toBe(1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.floatValue();
expect(output.get()).toBe(1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaByte("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaByte("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.BYTE);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaDate.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaDate } from "../JavaDate";
import { JavaType } from "../JavaType";
describe("get", () => {
test("with date, should return same value as Date", () => {
const input = new Date();
const output = new JavaDate(input).get();
expect(output).toEqual(input);
});
});
describe("set", () => {
test("with direct value, should set", () => {
const firstDate = new Date();
const input = new JavaDate(firstDate);
expect(input.get()).toEqual(firstDate);
const secondDate = new Date();
input.set(secondDate);
expect(input.get()).toEqual(secondDate);
});
test("with value from function, should set", () => {
const firstDate = new Date();
const input = new JavaDate(firstDate);
expect(input.get()).toEqual(firstDate);
input.set(cur => {
const newDate = new Date(cur.getUTCMilliseconds());
newDate.setHours(cur.getHours() + 1);
return newDate;
});
const expectedDate = new Date(firstDate.getUTCMilliseconds());
expectedDate.setHours(firstDate.getHours() + 1);
expect(input.get()).toEqual(expectedDate);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaDate(new Date()) as any)._fqcn;
expect(fqcn).toBe(JavaType.DATE);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaDouble.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaDouble } from "../JavaDouble";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive float, should return same value as number", () => {
const input = "12.24";
const output = new JavaDouble(input).get();
expect(output).toEqual(12.24);
});
test("negative float, should return same value as number", () => {
const input = "-12.24";
const output = new JavaDouble(input).get();
expect(output).toEqual(-12.24);
});
test("positive integer, should return same value as number", () => {
const input = "12";
const output = new JavaDouble(input).get();
expect(output).toEqual(12);
});
test("negative integer, should return same value as number", () => {
const input = "-12";
const output = new JavaDouble(input).get();
expect(output).toEqual(-12);
});
});
test("with invalid input string, should return NaN", () => {
const input = "abc";
const output = new JavaDouble(input).get();
expect(output).toBeNaN();
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as Number", () => {
const input = `${-Number.MAX_VALUE}`;
const output = new JavaDouble(input).get();
expect(output).toEqual(-Number.MAX_VALUE);
});
test("less than, should return same value as Number", () => {
const input = `${-Number.MAX_VALUE - 1}`;
const output = new JavaDouble(input).get();
expect(output).toEqual(-Number.MAX_VALUE - 1);
});
});
describe("maximum bound", () => {
test("equals, should return same value as Number", () => {
const input = `${Number.MAX_VALUE}`;
const output = new JavaDouble(input).get();
expect(output).toEqual(Number.MAX_VALUE);
});
test("greater than, should return same value as Number", () => {
const input = `${Number.MAX_VALUE + 1}`;
const output = new JavaDouble(input).get();
expect(output).toEqual(Number.MAX_VALUE + 1);
});
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaDouble("1");
expect(input.get()).toEqual(1);
input.set(2);
expect(input.get()).toEqual(2);
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaDouble("1");
expect(input.get()).toEqual(1);
input.set(Number.MAX_VALUE * 2);
expect(input.get()).toEqual(NaN);
});
test("with valid value from function, should set", () => {
const input = new JavaDouble("1");
expect(input.get()).toEqual(1);
input.set(cur => 2 + cur);
expect(input.get()).toEqual(3);
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaDouble("2");
expect(input.get()).toEqual(2);
input.set(cur => Number.MAX_VALUE * cur);
expect(input.get()).toEqual(NaN);
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1.1");
const output = input.doubleValue();
expect(output.get()).toBe(1.1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1.1");
const output = input.floatValue();
expect(output.get()).toBe(1.1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaDouble("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaDouble("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.DOUBLE);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaFloat.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaFloat } from "../JavaFloat";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive float, should return same value as BigNumber", () => {
const input = "12.92";
const output = new JavaFloat(input).get();
expect(output).toEqual(12.92);
});
test("negative float, should return same value as BigNumber", () => {
const input = "-12.92";
const output = new JavaFloat(input).get();
expect(output).toEqual(-12.92);
});
test("positive integer, should return same value as BigNumber", () => {
const input = "12";
const output = new JavaFloat(input).get();
expect(output).toEqual(12);
});
test("negative integer, should return same value as BigNumber", () => {
const input = "-12";
const output = new JavaFloat(input).get();
expect(output).toEqual(-12);
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaFloat(input).get();
expect(output).toBeNaN();
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = `${JavaFloat.MIN_VALUE}`;
const output = new JavaFloat(input).get();
expect(output).toEqual(JavaFloat.MIN_VALUE);
});
test("less than, should return NaN", () => {
const input = `${JavaFloat.MIN_VALUE - 1e23}`; // smaller value inside float's precision
const output = new JavaFloat(input).get();
expect(output).toBeNaN();
});
});
describe("maximum bound", () => {
test("equals, should return same value as BigNumber", () => {
const input = `${JavaFloat.MAX_VALUE}`;
const output = new JavaFloat(input).get();
expect(output).toEqual(JavaFloat.MAX_VALUE);
});
test("greater than, should return same value as BigNumber", () => {
const input = `${JavaFloat.MAX_VALUE + 1e23}`; // smaller value inside float's precision
const output = new JavaFloat(input).get();
expect(output).toEqual(NaN);
});
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaFloat("1");
expect(input.get()).toEqual(1);
input.set(2);
expect(input.get()).toEqual(2);
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaFloat("1");
expect(input.get()).toEqual(1);
input.set(JavaFloat.MAX_VALUE * 2);
expect(input.get()).toEqual(NaN);
});
test("with valid value from function, should set", () => {
const input = new JavaFloat("1");
expect(input.get()).toEqual(1);
input.set(cur => 2 + cur);
expect(input.get()).toEqual(3);
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaFloat("2");
expect(input.get()).toEqual(2);
input.set(cur => JavaFloat.MAX_VALUE * cur);
expect(input.get()).toEqual(NaN);
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1.1");
const output = input.doubleValue();
expect(output.get()).toBe(1.1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1.1");
const output = input.floatValue();
expect(output.get()).toBe(1.1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaFloat("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaFloat("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.FLOAT);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaHashMap.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaHashMap } from "../JavaHashMap";
import { JavaType } from "../JavaType";
describe("get", () => {
test("with populated map, returns the same map", () => {
const input = new Map([["foo1", "bar1"], ["foo2", "bar2"]]);
const output = new JavaHashMap(input).get();
expect(output).toEqual(new Map([["foo1", "bar1"], ["foo2", "bar2"]]));
});
test("with empty map, returns the same map", () => {
const input = new Map();
const output = new JavaHashMap(input).get();
expect(output).toEqual(new Map());
});
});
describe("set", () => {
test("with direct value, should set", () => {
const input = new JavaHashMap(new Map([["k1", "v1"]]));
expect(input.get()).toEqual(new Map([["k1", "v1"]]));
input.set(new Map([["k2", "v2"]]));
expect(input.get()).toEqual(new Map([["k2", "v2"]]));
});
test("with value from function, should set", () => {
const input = new JavaHashMap(new Map([["k1", "v1"]]));
expect(input.get()).toEqual(new Map([["k1", "v1"]]));
input.set(cur => {
const newMap = new Map(cur);
newMap.set("k2", "v2");
return newMap;
});
expect(input.get()).toEqual(new Map([["k1", "v1"], ["k2", "v2"]]));
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaHashMap(new Map([["foo1", "bar1"]])) as any)._fqcn;
expect(fqcn).toBe(JavaType.HASH_MAP);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaHashSet.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaHashSet } from "../JavaHashSet";
import { JavaType } from "../JavaType";
describe("get", () => {
test("with populated set, returns the same set", () => {
const input = new Set(["foo", "bar", "foo2"]);
const output = new JavaHashSet(input).get();
expect(output).toEqual(new Set(["foo", "bar", "foo2"]));
});
test("with empty set, returns the same set", () => {
const input = new Set();
const output = new JavaHashSet(input).get();
expect(output).toEqual(new Set());
});
});
describe("set", () => {
test("with direct value, should set", () => {
const input = new JavaHashSet(new Set(["k1", "v1"]));
expect(input.get()).toEqual(new Set(["k1", "v1"]));
input.set(new Set(["k2", "v2"]));
expect(input.get()).toEqual(new Set(["k2", "v2"]));
});
test("with value from function, should set", () => {
const input = new JavaHashSet(new Set(["k1", "v1"]));
expect(input.get()).toEqual(new Set(["k1", "v1"]));
input.set(cur => {
const newSet = new Set(cur);
newSet.add("k2");
return newSet;
});
expect(input.get()).toEqual(new Set(["k1", "v1", "k2"]));
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaHashSet(new Set(["1", "2"])) as any)._fqcn;
expect(fqcn).toBe(JavaType.HASH_SET);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaInteger.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaInteger } from "../JavaInteger";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive integer, should return same value as number", () => {
const input = "12";
const output = new JavaInteger(input).get();
expect(output).toEqual(12);
});
test("negative integer, should return same value as number", () => {
const input = "-12";
const output = new JavaInteger(input).get();
expect(output).toEqual(-12);
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaInteger(input).get();
expect(output).toBeNaN();
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaInteger.MIN_VALUE}`;
const output = new JavaInteger(input).get();
expect(output).toEqual(JavaInteger.MIN_VALUE);
});
test("less than, should return NaN", () => {
const input = `${JavaInteger.MIN_VALUE - 1}`;
const output = new JavaInteger(input).get();
expect(output).toEqual(NaN);
});
});
describe("maximum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaInteger.MAX_VALUE}`;
const output = new JavaInteger(input).get();
expect(output).toEqual(JavaInteger.MAX_VALUE);
});
test("greater than, should return NaN", () => {
const input = `${JavaInteger.MAX_VALUE + 1}`;
const output = new JavaInteger(input).get();
expect(output).toEqual(NaN);
});
});
});
describe("with float string", () => {
test("positive with decimal closest to 0, should return truncated value as Number", () => {
const input = "12.1";
const output = new JavaInteger(input).get();
expect(output).toEqual(12);
});
test("positive with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "12.5";
const output = new JavaInteger(input).get();
expect(output).toEqual(12);
});
test("positive with decimal closest to 1, should return truncated value as Number", () => {
const input = "12.9";
const output = new JavaInteger(input).get();
expect(output).toEqual(12);
});
test("negative with decimal closest to 0, should return truncated value as Number", () => {
const input = "-12.1";
const output = new JavaInteger(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "-12.5";
const output = new JavaInteger(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal closest to 1, should return truncated value as Number", () => {
const input = "-12.9";
const output = new JavaInteger(input).get();
expect(output).toEqual(-12);
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaInteger("1");
expect(input.get()).toEqual(1);
input.set(2);
expect(input.get()).toEqual(2);
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaInteger("1");
expect(input.get()).toEqual(1);
input.set(JavaInteger.MAX_VALUE + 1);
expect(input.get()).toEqual(NaN);
});
test("with valid value from function, should set", () => {
const input = new JavaInteger("1");
expect(input.get()).toEqual(1);
input.set(cur => 2 + cur);
expect(input.get()).toEqual(3);
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaInteger("1");
expect(input.get()).toEqual(1);
input.set(cur => JavaInteger.MAX_VALUE + cur);
expect(input.get()).toEqual(NaN);
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.doubleValue();
expect(output.get()).toBe(1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.floatValue();
expect(output.get()).toBe(1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaInteger("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaInteger("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.INTEGER);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaLong.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaLong } from "../JavaLong";
import { BigNumber } from "bignumber.js";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive integer, should return same value as number", () => {
const input = "12";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("negative integer, should return same value as number", () => {
const input = "-12";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber(NaN));
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaLong.MIN_VALUE}`;
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber(`${JavaLong.MIN_VALUE}`));
});
test("less than, should return NaN", () => {
const input = new BigNumber(`${JavaLong.MIN_VALUE}`).minus(1, 10);
const output = new JavaLong(input.toString(10)).get();
expect(output).toEqual(new BigNumber(NaN));
});
});
describe("maximum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaLong.MAX_VALUE}`;
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber(`${JavaLong.MAX_VALUE}`));
});
test("greater than, should return NaN", () => {
const input = new BigNumber(`${JavaLong.MAX_VALUE}`).plus(1, 10);
const output = new JavaLong(input.toString(10)).get();
expect(output).toEqual(new BigNumber(NaN));
});
});
});
describe("with float string", () => {
test("positive with decimal closest to 0, should return truncated value as Number", () => {
const input = "12.1";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("positive with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "12.5";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("positive with decimal closest to 1, should return truncated value as Number", () => {
const input = "12.9";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("12"));
});
test("negative with decimal closest to 0, should return truncated value as Number", () => {
const input = "-12.1";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
test("negative with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "-12.5";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
test("negative with decimal closest to 1, should return truncated value as Number", () => {
const input = "-12.9";
const output = new JavaLong(input).get();
expect(output).toEqual(new BigNumber("-12"));
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaLong("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(new BigNumber("2"));
expect(input.get()).toEqual(new BigNumber("2"));
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaLong("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(new BigNumber(`${JavaLong.MAX_VALUE}`).plus(1, 10));
expect(input.get()).toEqual(new BigNumber(NaN));
});
test("with valid value from function, should set", () => {
const input = new JavaLong("1");
expect(input.get()).toEqual(new BigNumber("1"));
input.set(cur => new BigNumber("2").plus(cur));
expect(input.get()).toEqual(new BigNumber("3"));
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaLong(`${JavaLong.MAX_VALUE}`);
expect(input.get()).toEqual(new BigNumber(`${JavaLong.MAX_VALUE}`));
input.set(cur => new BigNumber(`${JavaLong.MAX_VALUE}`).plus(cur));
expect(input.get()).toEqual(new BigNumber(NaN));
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.doubleValue();
expect(output.get()).toBe(1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.floatValue();
expect(output.get()).toBe(1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaLong("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaLong("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.LONG);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaOptional.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaOptional } from "../JavaOptional";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("defined element, should return same element", () => {
const input = "foo";
const output = new JavaOptional(input).get();
expect(output).toBe("foo");
});
test("undefined element, should throw error", () => {
const input = undefined;
const optional = new JavaOptional(input);
expect(() => optional.get()).toThrowError();
});
});
});
describe("set", () => {
test("with defined direct value, should set", () => {
const input = new JavaOptional("foo");
expect(input.get()).toEqual("foo");
input.set("bar");
expect(input.get()).toEqual("bar");
});
test("with undefined direct value, should set", () => {
const input = new JavaOptional("foo");
expect(input.get()).toEqual("foo");
input.set(undefined);
expect(() => input.get()).toThrowError();
});
test("with defined value from function, should set", () => {
const input = new JavaOptional("foo");
expect(input.get()).toEqual("foo");
input.set(cur => cur + "bar");
expect(input.get()).toEqual("foobar");
});
test("with undefined value from function, should set", () => {
const input = new JavaOptional("foo");
expect(input.get()).toEqual("foo");
input.set(_ => undefined);
expect(() => input.get()).toThrowError();
});
});
describe("ifPresent", () => {
test("with defined element, should return true", () => {
const input = new JavaOptional("str");
const output = input.isPresent();
expect(output).toBeTruthy();
});
test("with undefined element, should return true", () => {
const input = new JavaOptional(undefined);
const output = input.isPresent();
expect(output).toBeFalsy();
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaOptional("foo") as any)._fqcn;
expect(fqcn).toBe(JavaType.OPTIONAL);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaShort.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaShort } from "../JavaShort";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("positive integer, should return same value as number", () => {
const input = "12";
const output = new JavaShort(input).get();
expect(output).toEqual(12);
});
test("negative integer, should return same value as number", () => {
const input = "-12";
const output = new JavaShort(input).get();
expect(output).toEqual(-12);
});
});
test("with invalid textual string, should return NaN", () => {
const input = "abc";
const output = new JavaShort(input).get();
expect(output).toBeNaN();
});
describe("with input in the numeric bounds", () => {
describe("minimum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaShort.MIN_VALUE}`;
const output = new JavaShort(input).get();
expect(output).toEqual(JavaShort.MIN_VALUE);
});
test("less than, should return NaN", () => {
const input = `${JavaShort.MIN_VALUE - 1}`;
const output = new JavaShort(input).get();
expect(output).toEqual(NaN);
});
});
describe("maximum bound", () => {
test("equals, should return same value as number", () => {
const input = `${JavaShort.MAX_VALUE}`;
const output = new JavaShort(input).get();
expect(output).toEqual(JavaShort.MAX_VALUE);
});
test("greater than, should return NaN", () => {
const input = `${JavaShort.MAX_VALUE + 1}`;
const output = new JavaShort(input).get();
expect(output).toEqual(NaN);
});
});
});
describe("with float string", () => {
test("positive with decimal closest to 0, should return truncated value as Number", () => {
const input = "12.1";
const output = new JavaShort(input).get();
expect(output).toEqual(12);
});
test("positive with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "12.5";
const output = new JavaShort(input).get();
expect(output).toEqual(12);
});
test("positive with decimal closest to 1, should return truncated value as Number", () => {
const input = "12.9";
const output = new JavaShort(input).get();
expect(output).toEqual(12);
});
test("negative with decimal closest to 0, should return truncated value as Number", () => {
const input = "-12.1";
const output = new JavaShort(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal exactly between 0 and 1, should return truncated value as Number", () => {
const input = "-12.5";
const output = new JavaShort(input).get();
expect(output).toEqual(-12);
});
test("negative with decimal closest to 1, should return truncated value as Number", () => {
const input = "-12.9";
const output = new JavaShort(input).get();
expect(output).toEqual(-12);
});
});
});
describe("set", () => {
test("with valid direct value, should set", () => {
const input = new JavaShort("1");
expect(input.get()).toEqual(1);
input.set(2);
expect(input.get()).toEqual(2);
});
test("with invalid direct value, should set NaN", () => {
const input = new JavaShort("1");
expect(input.get()).toEqual(1);
input.set(JavaShort.MAX_VALUE + 1);
expect(input.get()).toEqual(NaN);
});
test("with valid value from function, should set", () => {
const input = new JavaShort("1");
expect(input.get()).toEqual(1);
input.set(cur => 2 + cur);
expect(input.get()).toEqual(3);
});
test("with invalid value from function, should set NaN", () => {
const input = new JavaShort("1");
expect(input.get()).toEqual(1);
input.set(cur => JavaShort.MAX_VALUE + cur);
expect(input.get()).toEqual(NaN);
});
});
describe("doubleValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.doubleValue();
expect(output.get()).toBe(1);
});
});
describe("intValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.intValue();
expect(output.get()).toBe(1);
});
});
describe("shortValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.shortValue();
expect(output.get()).toBe(1);
});
});
describe("byteValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.byteValue();
expect(output.get()).toBe(1);
});
});
describe("floatValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.floatValue();
expect(output.get()).toBe(1);
});
});
describe("longValue", () => {
test("should convert successfully", () => {
const input = new JavaShort("1");
const output = input.longValue();
expect(output.get().toNumber()).toBe(1);
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaShort("1") as any)._fqcn;
expect(fqcn).toBe(JavaType.SHORT);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaString.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaString } from "../JavaString";
import { JavaType } from "../JavaType";
describe("get", () => {
describe("with valid input", () => {
test("non-empty string, should return same string", () => {
const input = "foo";
const output = new JavaString(input).get();
expect(output).toBe("foo");
});
test("empty string, should return same string", () => {
const input = "";
const output = new JavaString(input).get();
expect(output).toBe("");
});
});
});
describe("set", () => {
test("with direct value, should set", () => {
const input = new JavaString("foo");
expect(input.get()).toBe("foo");
input.set("bar");
expect(input.get()).toBe("bar");
});
test("with value from function, should set", () => {
const input = new JavaString("foo");
expect(input.get()).toBe("foo");
input.set(cur => cur + "bar");
expect(input.get()).toBe("foobar");
});
});
describe("_fqcn", () => {
test("must be the same than in Java", () => {
const fqcn = (new JavaString("foo") as any)._fqcn;
expect(fqcn).toBe(JavaType.STRING);
});
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaWrapper.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapper } from "../JavaWrapper";
describe("extendsJavaWrapper", () => {
test("with class extending java wrapper, should return true", () => {
const input = new MyNumberType(1);
const output = JavaWrapper.extendsJavaWrapper(input);
expect(output).toBeTruthy();
});
test("with class not extending java wrapper, should return false", () => {
const input = {
foo: "bar"
};
const output = JavaWrapper.extendsJavaWrapper(input);
expect(output).toBeFalsy();
});
class MyNumberType extends JavaWrapper {
private _value: number;
constructor(value: number) {
super();
this._value = value;
}
public get(): number {
return this._value;
}
public set(val: ((current: number) => number) | number): void {
// not used
}
}
});
================================================
FILE: appformer-js/src/java-wrappers/__tests__/JavaWrapperUtils.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapperUtils } from "../JavaWrapperUtils";
import { JavaArrayList } from "../JavaArrayList";
import { JavaHashSet } from "../JavaHashSet";
import { JavaHashMap } from "../JavaHashMap";
import { JavaBoolean } from "../JavaBoolean";
import { JavaString } from "../JavaString";
import { JavaDate } from "../JavaDate";
import { JavaType } from "../JavaType";
import { JavaEnum } from "../JavaEnum";
describe("needsWrapping", () => {
test("with array object, should return true", () => {
const input = ["foo1", "foo2", "foo3"];
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with set object, should return true", () => {
const input = new Set(["foo1", "foo2", "foo3"]);
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with map object, should return true", () => {
const input = new Map([["foo1", "bar1"], ["foo2", "bar2"]]);
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with boolean object, should return true", () => {
const input = false;
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with string object, should return true", () => {
const input = "foo";
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with date object, should return true", () => {
const input = new Date();
expect(JavaWrapperUtils.needsWrapping(input)).toBeTruthy();
});
test("with custom object, should return false", () => {
const input = {
foo: "bar1",
foo2: "bar2"
};
expect(JavaWrapperUtils.needsWrapping(input)).toBeFalsy();
});
test("with enum type, should return false", () => {
const input = FooEnum.FOO;
expect(JavaWrapperUtils.needsWrapping(input)).toBeFalsy();
});
});
describe("wrapIfNeeded", () => {
test("with array object, should return a JavaArray instance", () => {
const input = ["foo1", "foo2", "foo3"];
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(new JavaArrayList(["foo1", "foo2", "foo3"]));
});
test("with set object, should return a JavaHashSet instance", () => {
const input = new Set(["foo1", "foo2", "foo3"]);
const output = new JavaHashSet(new Set(["foo1", "foo2", "foo3"]));
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(output);
});
test("with map object, should return a JavaHashMap instance", () => {
const input = new Map([["foo1", "bar1"], ["foo2", "bar2"]]);
const output = new JavaHashMap(new Map([["foo1", "bar1"], ["foo2", "bar2"]]));
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(output);
});
test("with boolean object, should return a JavaBoolean instance", () => {
const input = false;
const output = new JavaBoolean(false);
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(output);
});
test("with string object, should return a JavaString instance", () => {
const input = "foo";
const output = new JavaString("foo");
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(output);
});
test("with date object, should return a JavaDate instance", () => {
const input = new Date();
const output = new JavaDate(input);
expect(JavaWrapperUtils.wrapIfNeeded(input)).toEqual(output);
});
test("with custom object, should return same object", () => {
const input = {
foo: "bar1",
foo2: "bar2"
};
expect(JavaWrapperUtils.wrapIfNeeded(input)).toStrictEqual(input);
});
test("with enum value, should return same value", () => {
const input = FooEnum.BAR;
expect(JavaWrapperUtils.wrapIfNeeded(input)).toStrictEqual(input);
});
});
describe("isJavaType", () => {
test("with Java Byte's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.BYTE)).toBeTruthy();
});
test("with Java Double's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.DOUBLE)).toBeTruthy();
});
test("with Java Float's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.FLOAT)).toBeTruthy();
});
test("with Java Integer's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.INTEGER)).toBeTruthy();
});
test("with Java Long's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.LONG)).toBeTruthy();
});
test("with Java Short's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.SHORT)).toBeTruthy();
});
test("with Java Boolean's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.BOOLEAN)).toBeTruthy();
});
test("with Java String's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.STRING)).toBeTruthy();
});
test("with Java BigDecimal's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.BIG_DECIMAL)).toBeTruthy();
});
test("with Java BigInteger's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.BIG_INTEGER)).toBeTruthy();
});
test("with Java ArrayList's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.ARRAY_LIST)).toBeTruthy();
});
test("with Java HashSet's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.HASH_SET)).toBeTruthy();
});
test("with Java HashMap's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.HASH_MAP)).toBeTruthy();
});
test("with Java Date's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.DATE)).toBeTruthy();
});
test("with non Java type fqcn, should return false", () => {
expect(JavaWrapperUtils.isJavaType("foo")).toBeFalsy();
});
test("with Java Optional's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.OPTIONAL)).toBeTruthy();
});
test("with Java Enum's fqcn, should return true", () => {
expect(JavaWrapperUtils.isJavaType(JavaType.ENUM)).toBeTruthy();
});
});
describe("isEnum", () => {
test("with Enum input, should return true", () => {
const input = FooEnum.BAR;
expect(JavaWrapperUtils.isEnum(input)).toBeTruthy();
});
test("with non enum input, should return false", () => {
const input = {
foo: "bar"
};
expect(JavaWrapperUtils.isEnum(input)).toBeFalsy();
});
});
class FooEnum extends JavaEnum {
public static readonly FOO: FooEnum = new FooEnum("FOO");
public static readonly BAR: FooEnum = new FooEnum("BAR");
protected readonly _fqcn: string = FooEnum.__fqcn();
public static __fqcn(): string {
return "com.app.my.AddressType";
}
public static values() {
return [FooEnum.FOO, FooEnum.BAR];
}
}
================================================
FILE: appformer-js/src/java-wrappers/index.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export * from "./JavaArrayList";
export * from "./JavaHashMap";
export * from "./JavaHashSet";
export * from "./JavaByte";
export * from "./JavaDouble";
export * from "./JavaFloat";
export * from "./JavaInteger";
export * from "./JavaNumber";
export * from "./JavaLong";
export * from "./JavaShort";
export * from "./JavaBigInteger";
export * from "./JavaBigDecimal";
export * from "./JavaBoolean";
export * from "./JavaString";
export * from "./JavaDate";
export * from "./JavaOptional";
export * from "./JavaTreeMap";
export * from "./JavaTreeSet";
export * from "./JavaLinkedList";
export * from "./JavaEnum";
================================================
FILE: appformer-js/src/marshalling/Marshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "./MarshallingContext";
import { Portable } from "./Portable";
import { UnmarshallingContext } from "./UnmarshallingContext";
// marshall(T) => U
// unmarshall(V) => X
export interface Marshaller, U, V, X> {
marshall(input: T, ctx: MarshallingContext): U | null;
unmarshall(input: V | undefined, ctx: UnmarshallingContext): X | undefined;
}
================================================
FILE: appformer-js/src/marshalling/MarshallerProvider.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaWrapperUtils } from "../java-wrappers/JavaWrapperUtils";
import { JavaType } from "../java-wrappers/JavaType";
import { Marshaller } from "./Marshaller";
import { JavaHashMapMarshaller } from "./marshallers/JavaHashMapMarshaller";
import { JavaShortMarshaller } from "./marshallers/JavaShortMarshaller";
import { JavaDoubleMarshaller } from "./marshallers/JavaDoubleMarshaller";
import { DefaultMarshaller } from "./marshallers/DefaultMarshaller";
import { JavaStringMarshaller } from "./marshallers/JavaStringMarshaller";
import { JavaIntegerMarshaller } from "./marshallers/JavaIntegerMarshaller";
import { JavaBigIntegerMarshaller } from "./marshallers/JavaBigIntegerMarshaller";
import { JavaFloatMarshaller } from "./marshallers/JavaFloatMarshaller";
import { JavaBooleanMarshaller } from "./marshallers/JavaBooleanMarshaller";
import { JavaLongMarshaller } from "./marshallers/JavaLongMarshaller";
import { JavaBigDecimalMarshaller } from "./marshallers/JavaBigDecimalMarshaller";
import { JavaByteMarshaller } from "./marshallers/JavaByteMarshaller";
import { JavaDateMarshaller } from "./marshallers/JavaDateMarshaller";
import { JavaOptionalMarshaller } from "./marshallers/JavaOptionalMarshaller";
import { JavaArrayListMarshaller, JavaHashSetMarshaller } from "./marshallers/JavaCollectionMarshaller";
import { Portable } from "./Portable";
import { JavaEnumMarshaller } from "./marshallers/JavaEnumMarshaller";
export class MarshallerProvider {
private static initialized: boolean = false;
private static marshallersByJavaType: Map>;
private static defaultMarshaller: Marshaller;
public static initialize() {
if (this.initialized) {
return;
}
this.defaultMarshaller = new DefaultMarshaller();
this.marshallersByJavaType = new Map();
this.marshallersByJavaType.set(JavaType.BYTE, new JavaByteMarshaller());
this.marshallersByJavaType.set(JavaType.DOUBLE, new JavaDoubleMarshaller());
this.marshallersByJavaType.set(JavaType.FLOAT, new JavaFloatMarshaller());
this.marshallersByJavaType.set(JavaType.INTEGER, new JavaIntegerMarshaller());
this.marshallersByJavaType.set(JavaType.LONG, new JavaLongMarshaller());
this.marshallersByJavaType.set(JavaType.SHORT, new JavaShortMarshaller());
this.marshallersByJavaType.set(JavaType.BOOLEAN, new JavaBooleanMarshaller());
this.marshallersByJavaType.set(JavaType.STRING, new JavaStringMarshaller());
this.marshallersByJavaType.set(JavaType.DATE, new JavaDateMarshaller());
this.marshallersByJavaType.set(JavaType.BIG_DECIMAL, new JavaBigDecimalMarshaller());
this.marshallersByJavaType.set(JavaType.BIG_INTEGER, new JavaBigIntegerMarshaller());
this.marshallersByJavaType.set(JavaType.ARRAY_LIST, new JavaArrayListMarshaller());
this.marshallersByJavaType.set(JavaType.UNMODIFIABLE_COLLECTION, new JavaHashSetMarshaller());
this.marshallersByJavaType.set(JavaType.UNMODIFIABLE_SET, new JavaHashSetMarshaller());
this.marshallersByJavaType.set(JavaType.HASH_SET, new JavaHashSetMarshaller());
this.marshallersByJavaType.set(JavaType.HASH_MAP, new JavaHashMapMarshaller());
this.marshallersByJavaType.set(JavaType.UNMODIFIABLE_MAP, new JavaHashMapMarshaller());
this.marshallersByJavaType.set(JavaType.OPTIONAL, new JavaOptionalMarshaller());
this.marshallersByJavaType.set(JavaType.ENUM, new JavaEnumMarshaller());
this.initialized = true;
}
public static getForObject(obj: Portable): Marshaller {
this.assertInitialization();
if (obj === null || obj === undefined) {
return this.defaultMarshaller;
}
const fqcn = (obj as any)._fqcn;
if (!fqcn) {
return this.defaultMarshaller;
}
return this.getForFqcn(fqcn);
}
public static getForFqcn(fqcn: string): Marshaller {
this.assertInitialization();
if (!fqcn) {
return this.defaultMarshaller;
}
if (!JavaWrapperUtils.isJavaType(fqcn)) {
// portable objects defines an fqcn but we don't have specific marshallers for it.
return this.defaultMarshaller;
}
const marshaller = MarshallerProvider.marshallersByJavaType.get(fqcn);
if (!marshaller) {
throw new Error(`Missing marshaller implementation for type ${fqcn}`);
}
return marshaller;
}
public static getForEnum(): Marshaller {
return this.getForFqcn(JavaType.ENUM);
}
private static assertInitialization() {
if (!this.initialized) {
throw new Error("Initialize MarshallerProvider before using.");
}
}
}
================================================
FILE: appformer-js/src/marshalling/Marshalling.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Portable } from "./Portable";
import { MarshallerProvider } from "./MarshallerProvider";
import { MarshallingContext } from "./MarshallingContext";
import { UnmarshallingContext } from "./UnmarshallingContext";
import { ErraiObjectConstants } from "./model/ErraiObjectConstants";
/**
* Serializes a Portable object into an Errai json.
* @param obj
*/
export function marshall(obj: Portable): string | null {
if (obj === null || obj === undefined) {
return null;
}
const marshaller = MarshallerProvider.getForObject(obj);
return JSON.stringify(marshaller.marshall(obj, new MarshallingContext()));
}
/**
* Deserializes an Errai json creating a Portable object.
*
* @param json
* The Errai json.
* @param oracle
* A map containing fqcns as keys and a function returning an empty Portable associated with that fqcn.
*/
export function unmarshall(json: string, oracle: Map Portable>): Portable | null | void {
if (json === null || json === undefined) {
return undefined;
}
const jsonObj = JSON.parse(json);
const fqcn = jsonObj[ErraiObjectConstants.ENCODED_TYPE];
const marshaller = MarshallerProvider.getForFqcn(fqcn);
return marshaller.unmarshall(jsonObj, new UnmarshallingContext(oracle));
}
================================================
FILE: appformer-js/src/marshalling/MarshallingContext.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObject } from "./model/ErraiObject";
import { ErraiObjectConstants } from "./model/ErraiObjectConstants";
import { Portable } from "./Portable";
import { JavaWrapper } from "../java-wrappers/JavaWrapper";
export class MarshallingContext {
private objContext: Map, ErraiObject>;
private objectId: number;
constructor() {
this.objContext = new Map();
this.objectId = 0;
}
public incrementAndGetObjectId() {
return ++this.objectId;
}
public cacheObject(key: Portable, obj: ErraiObject) {
this.objContext.set(this.unwrap(key), {
[ErraiObjectConstants.ENCODED_TYPE]: obj[ErraiObjectConstants.ENCODED_TYPE],
[ErraiObjectConstants.OBJECT_ID]: obj[ErraiObjectConstants.OBJECT_ID]
});
}
public getCached(key: Portable): ErraiObject | undefined {
return this.objContext.get(this.unwrap(key))!;
}
private unwrap(key: Portable) {
if (JavaWrapper.extendsJavaWrapper(key)) {
// When handling wrapped values, we use the raw typescript value as cache key.
// This is needed because in the marshalling flow we wrap the values automatically
// if they represent a Java type, creating a new wrapper object every time. If we use the wrapper
// object directly, the value will never be found in cache, because it'll always be a different pointer
return key.get();
}
return key;
}
}
================================================
FILE: appformer-js/src/marshalling/Portable.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
// tslint:disable-next-line
export interface Portable> {}
================================================
FILE: appformer-js/src/marshalling/UnmarshallingContext.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { Portable } from "./Portable";
import { ErraiObject } from "./model/ErraiObject";
import { ErraiObjectConstants } from "./model/ErraiObjectConstants";
export class UnmarshallingContext {
private readonly _oracle: Map Portable>;
private readonly _objectsCache: Map>;
constructor(oracle: Map Portable>) {
this._oracle = oracle;
this._objectsCache = new Map();
}
public cacheObject(input: ErraiObject, obj: Portable) {
const objectId = input[ErraiObjectConstants.OBJECT_ID];
if (objectId) {
this._objectsCache.set(objectId, obj);
}
}
public getCached(input: ErraiObject): Portable | undefined {
const objectId = input[ErraiObjectConstants.OBJECT_ID];
if (!objectId) {
return undefined;
}
return this._objectsCache.get(objectId);
}
public getFactory(fqcn: string): (() => Portable) | undefined {
return this._oracle.get(fqcn);
}
}
================================================
FILE: appformer-js/src/marshalling/__tests__/MarshallerProvider.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../java-wrappers";
import { MarshallerProvider } from "../MarshallerProvider";
import { JavaBigIntegerMarshaller } from "../marshallers/JavaBigIntegerMarshaller";
import { JavaHashMapMarshaller } from "../marshallers/JavaHashMapMarshaller";
import { JavaByteMarshaller } from "../marshallers/JavaByteMarshaller";
import { JavaBigDecimalMarshaller } from "../marshallers/JavaBigDecimalMarshaller";
import { JavaStringMarshaller } from "../marshallers/JavaStringMarshaller";
import { JavaBooleanMarshaller } from "../marshallers/JavaBooleanMarshaller";
import { JavaShortMarshaller } from "../marshallers/JavaShortMarshaller";
import { JavaLongMarshaller } from "../marshallers/JavaLongMarshaller";
import { JavaIntegerMarshaller } from "../marshallers/JavaIntegerMarshaller";
import { JavaFloatMarshaller } from "../marshallers/JavaFloatMarshaller";
import { JavaDoubleMarshaller } from "../marshallers/JavaDoubleMarshaller";
import { DefaultMarshaller } from "../marshallers/DefaultMarshaller";
import { JavaWrapperUtils } from "../../java-wrappers/JavaWrapperUtils";
import { JavaType } from "../../java-wrappers/JavaType";
import * as JavaCollectionMarshaller from "../marshallers/JavaCollectionMarshaller";
import { JavaDateMarshaller } from "../marshallers/JavaDateMarshaller";
import { JavaOptionalMarshaller } from "../marshallers/JavaOptionalMarshaller";
describe("getForObject", () => {
test("without initialize, should return Error", () => {
const input = new JavaString("foo");
expect(() => MarshallerProvider.getForObject(input)).toThrowError();
});
describe("properly initialized", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
afterEach(() => {
// force reinitialization
(MarshallerProvider as any).initialized = false;
});
test("with JavaByte instance, should return JavaByteMarshaller instance", () => {
const input = new JavaByte("1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaByteMarshaller());
});
test("with JavaDouble instance, should return JavaDoubleMarshaller instance", () => {
const input = new JavaDouble("1.1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaDoubleMarshaller());
});
test("with JavaFloat instance, should return JavaFloatMarshaller instance", () => {
const input = new JavaFloat("1.1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaFloatMarshaller());
});
test("with JavaInteger instance, should return JavaIntegerMarshaller instance", () => {
const input = new JavaInteger("1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaIntegerMarshaller());
});
test("with JavaLong instance, should return JavaLongMarshaller instance", () => {
const input = new JavaLong("1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaLongMarshaller());
});
test("with JavaShort instance, should return JavaShortMarshaller instance", () => {
const input = new JavaShort("1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaShortMarshaller());
});
test("with JavaBoolean instance, should return JavaBooleanMarshaller instance", () => {
const input = new JavaBoolean(false);
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaBooleanMarshaller());
});
test("with JavaString instance, should return JavaStringMarshaller instance", () => {
const input = new JavaString("foo");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaStringMarshaller());
});
test("with JavaDate instance, should return JavaDateMarshaller instance", () => {
const input = new JavaDate(new Date());
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaDateMarshaller());
});
test("with JavaBigDecimal instance, should return JavaBigDecimalMarshaller instance", () => {
const input = new JavaBigDecimal("1.1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaBigDecimalMarshaller());
});
test("with JavaBigInteger instance, should return JavaBigIntegerMarshaller instance", () => {
const input = new JavaBigInteger("1");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaBigIntegerMarshaller());
});
test("with JavaArrayList instance, should return JavaArrayListMarshaller instance", () => {
const input = new JavaArrayList([1, 2, 3]);
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaCollectionMarshaller.JavaArrayListMarshaller());
});
test("with JavaHashSet instance, should return JavaHashSetMarshaller instance", () => {
const input = new JavaHashSet(new Set([1, 2, 3]));
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaCollectionMarshaller.JavaHashSetMarshaller());
});
test("with JavaHashMap instance, should return JavaHashMapMarshaller instance", () => {
const input = new JavaHashMap(new Map([["foo", "bar"]]));
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaHashMapMarshaller());
});
test("with JavaOptional instance, should return JavaOptionalMarshaller instance", () => {
const input = new JavaOptional("str");
expect(MarshallerProvider.getForObject(input)).toEqual(new JavaOptionalMarshaller());
});
test("with input without fqcn, should return default marshaller", () => {
const input = {
foo: "bar",
bar: "foo"
};
expect(MarshallerProvider.getForObject(input)).toEqual(new DefaultMarshaller());
});
test("with input with a custom fqcn, should return default marshaller", () => {
const fqcn = "com.myapp.custom.pojo";
const input = {
_fqcn: fqcn,
foo: "bar",
bar: "foo"
};
// it is a custom pojo (i.e. no pre-defined marshaller)
expect(JavaWrapperUtils.isJavaType(fqcn)).toBeFalsy();
expect(MarshallerProvider.getForObject(input)).toEqual(new DefaultMarshaller());
});
test("with a Java type without marshaller, should throw error", () => {
// the only scenario it throws errors is when a Java-wrapped type has no marshaller associated.
// little trick to mess with internal state
const marshallers = (MarshallerProvider as any).marshallersByJavaType;
marshallers.delete(JavaType.STRING);
const input = new JavaString("foo");
expect(() => MarshallerProvider.getForObject(input)).toThrowError();
});
});
});
describe("getForFqcn", () => {
test("without initialize, should return Error", () => {
expect(() => MarshallerProvider.getForFqcn("anything")).toThrowError();
});
describe("properly initialized", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
afterEach(() => {
// force reinitialization
(MarshallerProvider as any).initialized = false;
});
test("with Java's Byte fqcn, should return JavaByteMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.BYTE)).toEqual(new JavaByteMarshaller());
});
test("with Java's Double fqcn, should return JavaDoubleMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.DOUBLE)).toEqual(new JavaDoubleMarshaller());
});
test("with Java's Float fqcn, should return JavaFloatMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.FLOAT)).toEqual(new JavaFloatMarshaller());
});
test("with Java's Integer fqcn, should return JavaIntegerMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.INTEGER)).toEqual(new JavaIntegerMarshaller());
});
test("with Java's Long fqcn, should return JavaLongMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.LONG)).toEqual(new JavaLongMarshaller());
});
test("with Java's Short fqcn, should return JavaShortMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.SHORT)).toEqual(new JavaShortMarshaller());
});
test("with Java's Boolean fqcn, should return JavaBooleanMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.BOOLEAN)).toEqual(new JavaBooleanMarshaller());
});
test("with Java's String fqcn, should return JavaStringMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.STRING)).toEqual(new JavaStringMarshaller());
});
test("with Java's Date fqcn, should return JavaDateMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.DATE)).toEqual(new JavaDateMarshaller());
});
test("with Java's BigDecimal fqcn, should return JavaBigDecimalMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.BIG_DECIMAL)).toEqual(new JavaBigDecimalMarshaller());
});
test("with Java's BigInteger fqcn, should return JavaBigIntegerMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.BIG_INTEGER)).toEqual(new JavaBigIntegerMarshaller());
});
test("with Java's ArrayList fqcn, should return JavaArrayListMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.ARRAY_LIST)).toEqual(
new JavaCollectionMarshaller.JavaArrayListMarshaller()
);
});
test("with Java's HashSet fqcn, should return JavaHashSetMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.HASH_SET)).toEqual(
new JavaCollectionMarshaller.JavaHashSetMarshaller()
);
});
test("with Java's HashMap fqcn, should return JavaHashMapMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.HASH_MAP)).toEqual(new JavaHashMapMarshaller());
});
test("with Java's Optional fqcn, should return JavaOptionalMarshaller instance", () => {
expect(MarshallerProvider.getForFqcn(JavaType.OPTIONAL)).toEqual(new JavaOptionalMarshaller());
});
test("with null fqcn, should return default marshaller", () => {
const fqcn = null as any;
expect(MarshallerProvider.getForFqcn(fqcn)).toEqual(new DefaultMarshaller());
});
test("with undefined fqcn, should return default marshaller", () => {
const fqcn = undefined as any;
expect(MarshallerProvider.getForFqcn(fqcn)).toEqual(new DefaultMarshaller());
});
test("with empty string, should return default marshaller", () => {
const fqcn = "";
expect(MarshallerProvider.getForFqcn(fqcn)).toEqual(new DefaultMarshaller());
});
test("with custom fqcn, should return default marshaller", () => {
const fqcn = "com.myapp.custom.pojo";
// it is a custom pojo (i.e. no pre-defined marshaller)
expect(JavaWrapperUtils.isJavaType(fqcn)).toBeFalsy();
expect(MarshallerProvider.getForFqcn(fqcn)).toEqual(new DefaultMarshaller());
});
});
});
describe("consistency validations", () => {
beforeEach(() => {
(MarshallerProvider as any).initialized = false; // force reinitialization
MarshallerProvider.initialize();
});
test("all Java types should have a marshaller associated", () => {
// this test is important to avoid developers to forget to add marshallers to new JavaTypes
const marshallers = (MarshallerProvider as any).marshallersByJavaType;
Object.keys(JavaType)
.map((k: keyof typeof JavaType) => JavaType[k])
.forEach(javaType => expect(marshallers.get(javaType)).toBeDefined());
});
});
describe("getForEnum", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
afterEach(() => {
// force reinitialization
(MarshallerProvider as any).initialized = false;
});
test("should return exactly the same enum marshaller object", () => {
const enumMarshaller = (MarshallerProvider as any).marshallersByJavaType.get(JavaType.ENUM);
expect(MarshallerProvider.getForEnum()).toStrictEqual(enumMarshaller);
});
});
================================================
FILE: appformer-js/src/marshalling/__tests__/Marshalling.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallerProvider } from "../MarshallerProvider";
import * as Marshalling from "../Marshalling";
import { unmarshall } from "../Marshalling";
import { JavaInteger } from "../../java-wrappers";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
import { JavaType } from "../../java-wrappers/JavaType";
const originalGetForObject = MarshallerProvider.getForObject;
const originalGetForFqcn = MarshallerProvider.getForFqcn;
afterEach(() => {
// reset static function, otherwise other tests will be invoking the function set by this test
MarshallerProvider.getForFqcn = originalGetForFqcn;
MarshallerProvider.getForObject = originalGetForObject;
});
describe("marshall", () => {
test("with regular input, should return an errai object json-string version of it", () => {
const input = new JavaInteger("1");
const inputErraiObject = new NumValBasedErraiObject(JavaType.INTEGER, 1).asErraiObject();
const expectedJson = JSON.stringify(inputErraiObject);
// skip actual marshaller implementation
const mockedMarshaller = { marshall: jest.fn(() => inputErraiObject), unmarshall: jest.fn() };
MarshallerProvider.getForObject = jest.fn(() => mockedMarshaller);
// ==
// ====== test
const output = Marshalling.marshall(input);
// == assertion
expect(expectedJson).toEqual(output);
});
test("with null input, should return null", () => {
const input = null as any;
const output = Marshalling.marshall(input);
expect(output).toBeNull();
});
test("with undefined input, should serialize marshaller output", () => {
const input = undefined as any;
const output = Marshalling.marshall(input);
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with null input, should return undefined", () => {
const input = null;
const output = unmarshall(input as any, new Map());
expect(output).toBeUndefined();
});
test("with undefined input, should return undefined", () => {
const input = undefined;
const output = unmarshall(input as any, new Map());
expect(output).toBeUndefined();
});
test("with invalid json, should throw error", () => {
const input = "{ broken json }";
expect(() => unmarshall(input, new Map())).toThrowError();
});
test("with regular input, should return marshallers' specific content", () => {
const inputJson = new NumValBasedErraiObject(JavaType.INTEGER, 1).asErraiObject();
const expectedOutput = new JavaInteger("1");
// skip actual marshaller implementation
const mockedMarshaller = { unmarshall: jest.fn(() => expectedOutput), marshall: jest.fn() };
MarshallerProvider.getForFqcn = jest.fn(() => mockedMarshaller);
// ==
// ====== test
const output = Marshalling.unmarshall(JSON.stringify(inputJson), new Map());
// == assertion
expect(expectedOutput).toEqual(output);
});
});
================================================
FILE: appformer-js/src/marshalling/__tests__/MarshallingContext.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../MarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { ErraiObjectConstants } from "../model/ErraiObjectConstants";
import { JavaWrapper } from "../../java-wrappers/JavaWrapper";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
describe("incrementAndGetObjectId", () => {
test("with sequential calls, should return different ids", () => {
const context = new MarshallingContext();
const firstObjectId = context.incrementAndGetObjectId();
const secondObjectId = context.incrementAndGetObjectId();
expect(firstObjectId).not.toEqual(secondObjectId);
});
});
describe("cacheObject", () => {
let context: MarshallingContext;
beforeEach(() => {
context = new MarshallingContext();
});
test("with regular object, should record the correct ErraiObject instance", () => {
const inputPortable = { _fqcn: "com.myapp.my.portable", foo: "bar", bar: "foo" };
const inputErraiObject = new NumValBasedErraiObject("com.foo.bar", "123", "1").asErraiObject();
context.cacheObject(inputPortable, inputErraiObject);
// the only cached fields are the encodedType and objectId
expect((context as any).objContext.get(inputPortable)).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
});
});
test("with object overwritten, should return the last version", () => {
const inputPortable = { _fqcn: "com.myapp.my.portable", foo: "bar", bar: "foo" };
const inputErraiObject = new NumValBasedErraiObject("com.foo.bar", "123", "1").asErraiObject();
context.cacheObject(inputPortable, inputErraiObject);
// override object
context.cacheObject(inputPortable, {
...inputErraiObject,
[ErraiObjectConstants.OBJECT_ID]: "2"
});
expect((context as any).objContext.get(inputPortable)).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "2"
});
});
test("with java wrapper object, should use the inner value as cache key", () => {
const innerValue = 1;
const wrappedValue = new MyNumberWrappedType(innerValue);
const inputErraiObject = new NumValBasedErraiObject("com.foo.bar", "123", "1").asErraiObject();
context.cacheObject(wrappedValue, inputErraiObject);
// use the inner value object as cache key
expect((context as any).objContext.get(innerValue)).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
});
// do not use the wrapped object as cache key
expect((context as any).objContext.get(wrappedValue)).toBeUndefined();
});
});
describe("getCached", () => {
let context: MarshallingContext;
beforeEach(() => {
context = new MarshallingContext();
});
test("with non-existent key, should return undefined", () => {
const input = { _fqcn: "com.myapp.my.portable", foo: "bar", bar: "foo" };
expect(context.getCached(input)).toBeUndefined();
});
test("with existent key, should same object recorded previously", () => {
const inputPortable = { _fqcn: "com.myapp.my.portable", foo: "bar", bar: "foo" };
const inputErraiObject = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
} as ErraiObject;
(context as any).objContext.set(inputPortable, inputErraiObject);
expect(context.getCached(inputPortable)).toStrictEqual(inputErraiObject);
});
test("with java wrapper object, should use the inner value as cache key", () => {
const innerValue = 1;
const wrappedValue = new MyNumberWrappedType(innerValue);
const inputErraiObject = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
} as ErraiObject;
(context as any).objContext.set(innerValue, inputErraiObject);
// use the inner value object as cache key
expect(context.getCached(innerValue)).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
});
expect(context.getCached(wrappedValue)).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.foo.bar",
[ErraiObjectConstants.OBJECT_ID]: "1"
});
});
});
class MyNumberWrappedType extends JavaWrapper {
private readonly _fqcn = "com.type.wrapped.number.my";
private readonly _value: number;
constructor(value: number) {
super();
this._value = value;
}
public get(): number {
return this._value;
}
public set(val: ((current: number) => number) | number): void {
// not used
}
}
================================================
FILE: appformer-js/src/marshalling/__tests__/UnmarshallingContext.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { UnmarshallingContext } from "../UnmarshallingContext";
import { Portable } from "../Portable";
import { ErraiObjectConstants } from "../model/ErraiObjectConstants";
describe("cacheObject", () => {
test("with regular input, should cache it using the object's id as key", () => {
const context = new UnmarshallingContext(new Map());
const erraiObj = {
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "1",
foo: "bar"
};
const portable = new MyPortable({ foo: "bar" });
context.cacheObject(erraiObj, portable);
const cache = (context as any)._objectsCache;
const cachedValue = cache.get("1");
expect(cachedValue).toStrictEqual(portable);
expect(cache.size).toBe(1);
});
test("with repeated calls, should cache the last version", () => {
const context = new UnmarshallingContext(new Map());
const erraiObj = {
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "1",
foo: "bar"
};
const portable = new MyPortable({ foo: "bar" });
const portableV2 = new MyPortable({ foo: "bar2" });
context.cacheObject(erraiObj, portable);
context.cacheObject(erraiObj, portableV2);
const cache = (context as any)._objectsCache;
const cachedValue = cache.get("1");
expect(cachedValue).toStrictEqual(portableV2);
expect(cache.size).toBe(1);
});
test("with input without object id, should not cache it", () => {
const context = new UnmarshallingContext(new Map());
const erraiObj = {
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "",
foo: "bar"
};
const portable = new MyPortable({ foo: "bar" });
context.cacheObject(erraiObj, portable);
const cache = (context as any)._objectsCache;
const cachedValue = cache.get("1");
expect(cachedValue).toBeUndefined();
expect(cache.size).toBe(0);
});
});
describe("getCached", () => {
test("with cached input, should return it", () => {
const context = new UnmarshallingContext(new Map());
const erraiObj = {
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "1",
foo: "bar"
};
const portable = new MyPortable({ foo: "bar" });
context.cacheObject(erraiObj, portable);
const cachedValue = context.getCached(erraiObj);
expect(cachedValue).toStrictEqual(portable);
});
test("with input without object id, should return undefined", () => {
const context = new UnmarshallingContext(new Map());
const spy = jest.spyOn((context as any)._objectsCache, "get");
const erraiObj = {
// no object id
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "",
foo: "bar"
};
context.getCached(erraiObj);
expect(spy).not.toHaveBeenCalled();
});
test("with non existent input, should return undefined", () => {
const context = new UnmarshallingContext(new Map());
// add some dummy entry to the cache
const erraiObj = {
[ErraiObjectConstants.ENCODED_TYPE]: "bla",
[ErraiObjectConstants.OBJECT_ID]: "1",
foo: "bar"
};
const cachedValue = context.getCached(erraiObj);
expect(cachedValue).toBeUndefined();
expect((context as any)._objectsCache.size).toEqual(0);
});
});
describe("getFactory", () => {
test("with existent factory for fqcn, should return it", () => {
const oracle = new Map([["com.app.my", () => new MyPortable({} as any)]]);
const context = new UnmarshallingContext(oracle);
const factory = context.getFactory("com.app.my");
expect(factory).toBeDefined();
expect(factory!()).toEqual(new MyPortable({} as any));
});
test("with non-existent factory for fqcn, should return it", () => {
const oracle = new Map([["com.app.my2", () => new MyPortable({} as any)]]);
const context = new UnmarshallingContext(oracle);
const factory = context.getFactory("com.app.my");
expect(factory).toBeUndefined();
});
});
class MyPortable implements Portable {
private readonly _fqcn = "com.app.my";
public readonly foo: string;
constructor(self: { foo: string }) {
Object.assign(this, self);
}
}
================================================
FILE: appformer-js/src/marshalling/index.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallerProvider } from "./MarshallerProvider";
export * from "./Marshalling";
export * from "./Portable";
// Load marshallers to be used in RPC flow
MarshallerProvider.initialize();
================================================
FILE: appformer-js/src/marshalling/marshallers/DefaultMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallerProvider } from "../MarshallerProvider";
import { MarshallingContext } from "../MarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { JavaWrapperUtils } from "../../java-wrappers/JavaWrapperUtils";
import { ErraiObjectConstants } from "../model/ErraiObjectConstants";
import { Portable } from "../Portable";
import { NullableMarshaller } from "./NullableMarshaller";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { JavaWrapper } from "../../java-wrappers/JavaWrapper";
export class DefaultMarshaller> extends NullableMarshaller<
T,
ErraiObject,
ErraiObject,
Portable
> {
public notNullMarshall(input: T, ctx: MarshallingContext): ErraiObject {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return cachedObject;
}
const rootFqcn = (input as any)._fqcn;
if (!rootFqcn) {
// the input may be of primitive type, if it is a Java-wrappable type,
// we need to wrap it before marshalling
if (JavaWrapperUtils.needsWrapping(input)) {
return DefaultMarshaller.marshallWrappableType(input, ctx);
} else {
throw new Error(`Don't know how to marshall ${input}. Portable types must contain a '_fqcn' property!`);
}
}
// Input has fqcn, so, it represents a Java type. We need to check if it
// is a primitive Java type or not, because this marshaller handles only
// custom types (i.e. Portable).
if (JavaWrapperUtils.isJavaType(rootFqcn)) {
const marshaller = MarshallerProvider.getForObject(input);
const marshalledObject = marshaller.marshall(input, ctx);
ctx.cacheObject(input, marshalledObject);
return marshalledObject;
}
if (JavaWrapperUtils.isEnum(input)) {
return MarshallerProvider.getForEnum().marshall(input, ctx);
}
const _this = this.marshallCustomObject(input, ctx, rootFqcn);
ctx.cacheObject(input, _this);
return _this;
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): Portable {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return cachedObject;
}
const rootFqcn = input[ErraiObjectConstants.ENCODED_TYPE];
if (!rootFqcn) {
return DefaultMarshaller.unmarshallUnqualifiedValue(input, ctx);
}
const targetFactory = ctx.getFactory(rootFqcn);
if (!targetFactory) {
// this input is not a custom object, otherwise, we would be able to find a factory function.
// try to unmarshall it as a java type (that we know how to build)
return DefaultMarshaller.unmarshallJavaType(rootFqcn, input, ctx);
}
if (this.isEnumObject(input as any)) {
return MarshallerProvider.getForEnum().unmarshall(input, ctx);
}
const targetObj = this.unmarshallCustomObject(targetFactory, input, ctx);
ctx.cacheObject(input, targetObj);
return targetObj;
}
private marshallCustomObject(input: any, ctx: MarshallingContext, fqcn: string) {
const _this = { ...input };
Object.keys(_this).forEach(k => {
if (typeof _this[k] === "function") {
delete _this[k];
} else if (_this[k] === undefined || _this[k] === null) {
_this[k] = null;
} else if (_this[k]._fqcn) {
const marshaller = MarshallerProvider.getForObject(_this[k]);
_this[k] = marshaller.marshall(_this[k], ctx);
} else {
_this[k] = this.marshall(_this[k], ctx);
}
});
_this[ErraiObjectConstants.ENCODED_TYPE] = fqcn;
_this[ErraiObjectConstants.OBJECT_ID] = `${ctx.incrementAndGetObjectId()}`;
delete _this._fqcn;
return _this;
}
private unmarshallCustomObject(targetFactory: () => any, input: ErraiObject, ctx: UnmarshallingContext) {
// instantiate an empty target object in order to be able to discover the
// types of unqualified values present in the JSON
const targetObj = targetFactory();
// clone the input, removing non useful fields
const _this = { ...(input as any) };
delete _this[ErraiObjectConstants.ENCODED_TYPE];
delete _this[ErraiObjectConstants.OBJECT_ID];
Object.keys(_this).forEach(k => {
if (_this[k] === null || _this[k] === undefined) {
targetObj[k] = undefined;
} else if (_this[k][ErraiObjectConstants.ENCODED_TYPE]) {
const fqcn = _this[k][ErraiObjectConstants.ENCODED_TYPE];
targetObj[k] = MarshallerProvider.getForFqcn(fqcn).unmarshall(_this[k], ctx);
} else {
// no fqcn, try to infer it asking the field's type to the target object
const inferredFqcn = DefaultMarshaller.qualifyValue(k, _this[k], targetObj);
if (!inferredFqcn) {
throw new Error(`Don't know how to unmarshall field ${k} of ${input}`);
}
targetObj[k] = MarshallerProvider.getForFqcn(inferredFqcn).unmarshall(_this[k], ctx);
}
});
return targetObj;
}
private isEnumObject(input: ErraiObject): boolean {
return input[ErraiObjectConstants.ENUM_STRING_VALUE] !== undefined;
}
private static marshallWrappableType(input: any, ctx: MarshallingContext): any {
// convert native JS types to a default Java type implementation
const wrappedType = JavaWrapperUtils.wrapIfNeeded(input);
return MarshallerProvider.getForObject(wrappedType).marshall(wrappedType, ctx);
}
private static unmarshallJavaType(fqcn: string, input: ErraiObject, ctx: UnmarshallingContext) {
if (!JavaWrapperUtils.isJavaType(fqcn)) {
throw new Error(`No factory provided for ${fqcn}. Cannot unmarshall.`);
}
return MarshallerProvider.getForFqcn(fqcn).unmarshall(input, ctx);
}
private static unmarshallUnqualifiedValue(input: ErraiObject, ctx: UnmarshallingContext) {
if (!JavaWrapperUtils.needsWrapping(input)) {
// field is not wrappable, so, there's no way to know what is the target object
throw new Error("Don't know how to unmarshall types without encoded type");
}
// qualify the input (i.e. discover its fqcn)
const wrappedType = JavaWrapperUtils.wrapIfNeeded(input);
return MarshallerProvider.getForObject(wrappedType).unmarshall((wrappedType as JavaWrapper).get(), ctx);
}
private static qualifyValue(fieldName: string, fieldValue: any, targetObj: any): string | undefined {
if (JavaWrapperUtils.needsWrapping(fieldValue)) {
return (JavaWrapperUtils.wrapIfNeeded(fieldValue) as any)._fqcn;
}
if (targetObj[fieldName] === null || targetObj[fieldName] === undefined) {
return undefined;
}
return (targetObj[fieldName] as any)._fqcn;
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaBigDecimalMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaBigDecimal } from "../../java-wrappers/JavaBigDecimal";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
import { isString } from "../../util/TypeUtils";
export class JavaBigDecimalMarshaller extends NullableMarshaller<
JavaBigDecimal,
ErraiObject,
ErraiObject,
JavaBigDecimal
> {
public notNullMarshall(input: JavaBigDecimal, ctx: MarshallingContext): ErraiObject {
const fqcn = (input as any)._fqcn;
const value = input.get().toString(10);
const objectId = ctx.incrementAndGetObjectId().toString(10);
return new ValueBasedErraiObject(fqcn, value, objectId).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): JavaBigDecimal {
const valueFromJson = ValueBasedErraiObject.from(input).value as string;
if (!JavaBigDecimalMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid BigDecimal value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaBigDecimal(valueFromJson);
}
private static isValid(valueFromJson: string): boolean {
if (!valueFromJson) {
return false;
}
if (!isString(valueFromJson)) {
return false;
}
return NumberUtils.isFloatString(valueFromJson);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaBigIntegerMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaBigInteger } from "../../java-wrappers/JavaBigInteger";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
import { isString } from "../../util/TypeUtils";
export class JavaBigIntegerMarshaller extends NullableMarshaller<
JavaBigInteger,
ErraiObject,
ErraiObject,
JavaBigInteger
> {
public notNullMarshall(input: JavaBigInteger, ctx: MarshallingContext): ErraiObject {
const fqcn = (input as any)._fqcn;
const value = input.get().toString(10);
const objectId = ctx.incrementAndGetObjectId().toString(10);
return new ValueBasedErraiObject(fqcn, value, objectId).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): JavaBigInteger {
const valueFromJson = ValueBasedErraiObject.from(input).value as string;
if (!JavaBigIntegerMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid BigInteger value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaBigInteger(valueFromJson);
}
private static isValid(valueFromJson: string): boolean {
if (!isString(valueFromJson)) {
return false;
}
if (!valueFromJson) {
return false;
}
return NumberUtils.isIntegerString(valueFromJson);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaBooleanMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaBoolean } from "../../java-wrappers/JavaBoolean";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { instanceOfBoolean } from "../../util/TypeUtils";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
export class JavaBooleanMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaBoolean, ctx: MarshallingContext): boolean {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | boolean, ctx: UnmarshallingContext): boolean {
if (instanceOfBoolean(input)) {
return input;
}
const valueFromJson = NumValBasedErraiObject.from(input).numVal;
if (!JavaBooleanMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid boolean value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return valueFromJson as boolean;
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
return instanceOfBoolean(valueFromJson);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaByteMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaByte } from "../../java-wrappers/JavaByte";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { instanceOfNumber } from "../../util/TypeUtils";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
export class JavaByteMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaByte, ctx: MarshallingContext): number {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | number, ctx: UnmarshallingContext): JavaByte {
const valueFromJson = instanceOfNumber(input) ? input : NumValBasedErraiObject.from(input).numVal;
if (!JavaByteMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid byte value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaByte(`${valueFromJson}`);
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
if (!instanceOfNumber(valueFromJson)) {
return false;
}
return NumberUtils.isIntegerString(`${valueFromJson}`);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaCollectionMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaCollection } from "../../java-wrappers/JavaCollection";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { Portable } from "../Portable";
import { NullableMarshaller } from "./NullableMarshaller";
import { GenericsTypeMarshallingUtils } from "./util/GenericsTypeMarshallingUtils";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { isArray } from "../../util/TypeUtils";
import { JavaArrayList, JavaHashSet } from "../../java-wrappers";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { MarshallerProvider } from "../MarshallerProvider";
abstract class JavaCollectionMarshaller | null>> extends NullableMarshaller<
JavaCollection,
ErraiObject,
ErraiObject,
T
> {
public notNullMarshall(input: JavaCollection, ctx: MarshallingContext): ErraiObject {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return cachedObject;
}
const elements = input.get();
const serializedValues = [];
for (const element of Array.from(elements)) {
serializedValues.push(GenericsTypeMarshallingUtils.marshallGenericsTypeElement(element, ctx));
}
const fqcn = (input as any)._fqcn;
const value = serializedValues;
const objectId = ctx.incrementAndGetObjectId().toString(10);
const resultObject = new ValueBasedErraiObject(fqcn, value, objectId).asErraiObject();
ctx.cacheObject(input, resultObject);
return resultObject;
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): T {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return (cachedObject as JavaCollection).get();
}
const collection = ValueBasedErraiObject.from(input).value;
if (!JavaCollectionMarshaller.isValid(collection)) {
throw new Error(`Invalid collection value ${collection}. Can't unmarshall json ${input}`);
}
const unmarshalledValues = [];
for (const element of Array.from(collection)) {
unmarshalledValues.push(MarshallerProvider.getForObject(element).unmarshall(element, ctx));
}
const javaCollection = this.fromArray(unmarshalledValues);
ctx.cacheObject(input, javaCollection);
return javaCollection.get();
}
protected abstract fromArray(values: Array>): JavaCollection;
private static isValid(input: any): boolean {
if (input === null || input === undefined) {
return false;
}
// inside the json, all collections are represented as an array
return isArray(input);
}
}
export class JavaArrayListMarshaller extends JavaCollectionMarshaller | null>> {
protected fromArray(values: Array>): JavaArrayList> {
return new JavaArrayList(values);
}
}
export class JavaHashSetMarshaller extends JavaCollectionMarshaller | null>> {
protected fromArray(values: Array>): JavaHashSet> {
return new JavaHashSet(new Set(values));
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaDateMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaDate } from "../../java-wrappers/JavaDate";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { isString } from "../../util/TypeUtils";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
export class JavaDateMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaDate, ctx: MarshallingContext): ErraiObject {
return new ValueBasedErraiObject((input as any)._fqcn, `${input.get().getTime()}`).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): Date {
const valueFromJson = ValueBasedErraiObject.from(input).value;
if (!JavaDateMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid date value ${valueFromJson}. Can't unmarshall json ${input}`);
}
const asNumber = Number.parseInt(valueFromJson, 10);
return new Date(asNumber);
}
private static isValid(input: any) {
if (!input) {
return false;
}
if (!isString(input)) {
return false;
}
return NumberUtils.isNonNegativeIntegerString(input);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaDoubleMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaDouble } from "../../java-wrappers/JavaDouble";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { instanceOfNumber } from "../../util/TypeUtils";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
export class JavaDoubleMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaDouble, ctx: MarshallingContext): number {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | number, ctx: UnmarshallingContext): JavaDouble {
if (instanceOfNumber(input)) {
return new JavaDouble(`${input}`);
}
const valueFromJson = NumValBasedErraiObject.from(input).numVal;
if (!JavaDoubleMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid double value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaDouble(`${valueFromJson}`);
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
return instanceOfNumber(valueFromJson);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaEnumMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaEnum } from "../../java-wrappers";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { EnumStringValueBasedErraiObject } from "../model/EnumStringValueBasedErraiObject";
export class JavaEnumMarshaller> extends NullableMarshaller<
JavaEnum,
ErraiObject,
ErraiObject,
JavaEnum
> {
public notNullMarshall(input: JavaEnum, ctx: MarshallingContext): ErraiObject {
return new EnumStringValueBasedErraiObject((input as any)._fqcn, input.name).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): JavaEnum {
const valueObject = EnumStringValueBasedErraiObject.from(input);
const factory = ctx.getFactory(valueObject.encodedType);
// the factory method for enums receives the enum name and returns the appropriate enum value
return (factory as any)(valueObject.enumValueName);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaFloatMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaFloat } from "../../java-wrappers/JavaFloat";
import { MarshallingContext } from "../MarshallingContext";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { instanceOfNumber } from "../../util/TypeUtils";
import { ErraiObject } from "../model/ErraiObject";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
export class JavaFloatMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaFloat, ctx: MarshallingContext): number {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | number, ctx: UnmarshallingContext): JavaFloat {
if (instanceOfNumber(input)) {
return new JavaFloat(`${input}`);
}
const valueFromJson = NumValBasedErraiObject.from(input).numVal;
if (!JavaFloatMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid float value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaFloat(`${valueFromJson}`);
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
return instanceOfNumber(valueFromJson);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaHashMapMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NullableMarshaller } from "./NullableMarshaller";
import { ErraiObjectConstants } from "../model/ErraiObjectConstants";
import { GenericsTypeMarshallingUtils } from "./util/GenericsTypeMarshallingUtils";
import { JavaHashMap } from "../../java-wrappers/JavaHashMap";
import { MarshallingContext } from "../MarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { isString } from "../../util/TypeUtils";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { MarshallerProvider } from "../MarshallerProvider";
export class JavaHashMapMarshaller extends NullableMarshaller<
JavaHashMap,
ErraiObject,
ErraiObject,
Map
> {
public notNullMarshall(input: JavaHashMap, ctx: MarshallingContext): ErraiObject {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return cachedObject;
}
const marshalledEntriesMap = this.marshallEntries(input.get().entries(), ctx);
const fqcn = (input as any)._fqcn;
const value = marshalledEntriesMap;
const objectId = ctx.incrementAndGetObjectId().toString(10);
const result = new ValueBasedErraiObject(fqcn, value, objectId).asErraiObject();
ctx.cacheObject(input, result);
return result;
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): Map {
const cachedObject = ctx.getCached(input);
if (cachedObject) {
return (cachedObject as JavaHashMap).get();
}
const mapObj = ValueBasedErraiObject.from(input).value;
if (!mapObj) {
throw new Error(`Invalid Map value ${mapObj}. Can't unmarshall json ${input}`);
}
const map = this.unmarshallEntries(mapObj, ctx);
ctx.cacheObject(input, map);
return map.get();
}
private marshallEntries(entries: IterableIterator<[T, U]>, ctx: MarshallingContext) {
return Array.from(entries)
.map(([key, value]) => this.marshallEntry(key, value, ctx))
.reduce((acc, cur) => ({ ...acc, ...cur }), {});
}
private marshallEntry(key: T, value: U, ctx: MarshallingContext) {
const marshalledKey = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(key, ctx);
const marshalledValue = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(value, ctx);
if (marshalledKey === null) {
return { [ErraiObjectConstants.NULL]: marshalledValue };
}
if (!isString(marshalledKey)) {
// need to prefix the key in order to tell errai-marshalling that the key is not a native string
return { [ErraiObjectConstants.JSON + JSON.stringify(marshalledKey)]: marshalledValue };
}
return { [`${marshalledKey}`]: marshalledValue };
}
private unmarshallEntries(map: any, ctx: UnmarshallingContext): JavaHashMap {
const unmarshalledMap = new Map();
Object.keys(map).forEach(key => {
const unmarshalledKey = this.unmarshallKey(key, ctx);
const unmarshalledValue = MarshallerProvider.getForObject(map[key]).unmarshall(map[key], ctx);
unmarshalledMap.set(unmarshalledKey, unmarshalledValue);
});
return new JavaHashMap(unmarshalledMap);
}
private unmarshallKey(key: string, ctx: UnmarshallingContext): T | undefined {
if (!key) {
throw new Error(`Invalid Map's key ${key}. Can't unmarshall json!`);
}
if (key === ErraiObjectConstants.NULL) {
return undefined;
}
if (key.startsWith(ErraiObjectConstants.JSON)) {
// this prefix indicates that the key is not a native string, it is a json object serialized to string
const keyJson = JSON.parse(key.replace(ErraiObjectConstants.JSON, ""));
return MarshallerProvider.getForObject(keyJson).unmarshall(keyJson, ctx);
}
// the map key has type string
return key as any;
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaIntegerMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../MarshallingContext";
import { JavaInteger } from "../../java-wrappers/JavaInteger";
import { NullableMarshaller } from "./NullableMarshaller";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ErraiObject } from "../model/ErraiObject";
import { instanceOfNumber } from "../../util/TypeUtils";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
export class JavaIntegerMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaInteger, ctx: MarshallingContext): number {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | number, ctx: UnmarshallingContext): JavaInteger {
const valueFromJson = instanceOfNumber(input) ? input : NumValBasedErraiObject.from(input).numVal;
if (!JavaIntegerMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid integer value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaInteger(`${valueFromJson}`);
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
if (!instanceOfNumber(valueFromJson)) {
return false;
}
return NumberUtils.isIntegerString(`${valueFromJson}`);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaLongMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaLong } from "../../java-wrappers/JavaLong";
import { ErraiObject } from "../model/ErraiObject";
import { MarshallingContext } from "../MarshallingContext";
import { NullableMarshaller } from "./NullableMarshaller";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
export class JavaLongMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaLong, ctx: MarshallingContext): ErraiObject {
const asString = `${input.get().toString(10)}`;
return new NumValBasedErraiObject((input as any)._fqcn, asString).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): JavaLong {
const valueFromJson = NumValBasedErraiObject.from(input).numVal as string;
if (!JavaLongMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid long value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaLong(valueFromJson);
}
private static isValid(jsonValue: string) {
if (jsonValue === null || jsonValue === undefined) {
return false;
}
return NumberUtils.isIntegerString(jsonValue);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaOptionalMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../MarshallingContext";
import { NullableMarshaller } from "./NullableMarshaller";
import { JavaOptional } from "../../java-wrappers/JavaOptional";
import { ErraiObject } from "../model/ErraiObject";
import { GenericsTypeMarshallingUtils } from "./util/GenericsTypeMarshallingUtils";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { ValueBasedErraiObject } from "../model/ValueBasedErraiObject";
import { MarshallerProvider } from "../MarshallerProvider";
export class JavaOptionalMarshaller extends NullableMarshaller<
JavaOptional,
ErraiObject,
ErraiObject,
JavaOptional
> {
public notNullMarshall(input: JavaOptional, ctx: MarshallingContext): ErraiObject {
const innerValue = this.retrieveOptionalInnerValue(input, ctx);
return new ValueBasedErraiObject((input as any)._fqcn, innerValue).asErraiObject();
}
public notNullUnmarshall(input: ErraiObject, ctx: UnmarshallingContext): JavaOptional {
const value = ValueBasedErraiObject.from(input).value;
if (value === null || value === undefined) {
return new JavaOptional(undefined);
}
const unmarshalledValue = MarshallerProvider.getForObject(value).unmarshall(value, ctx);
return new JavaOptional(unmarshalledValue);
}
private retrieveOptionalInnerValue(input: JavaOptional, ctx: MarshallingContext) {
if (!input.isPresent()) {
return null;
}
return GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input.get(), ctx);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaShortMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaShort } from "../../java-wrappers/JavaShort";
import { MarshallingContext } from "../MarshallingContext";
import { NullableMarshaller } from "./NullableMarshaller";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { instanceOfNumber } from "../../util/TypeUtils";
import { ErraiObject } from "../model/ErraiObject";
import { NumValBasedErraiObject } from "../model/NumValBasedErraiObject";
import { NumberUtils } from "../../util/NumberUtils";
export class JavaShortMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaShort, ctx: MarshallingContext): number {
return input.get();
}
public notNullUnmarshall(input: ErraiObject | number, ctx: UnmarshallingContext): JavaShort {
const valueFromJson = instanceOfNumber(input) ? input : NumValBasedErraiObject.from(input).numVal;
if (!JavaShortMarshaller.isValid(valueFromJson)) {
throw new Error(`Invalid short value ${valueFromJson}. Can't unmarshall json ${input}`);
}
return new JavaShort(`${valueFromJson}`);
}
private static isValid(valueFromJson: any): boolean {
if (valueFromJson === null || valueFromJson === undefined) {
return false;
}
if (!instanceOfNumber(valueFromJson)) {
return false;
}
return NumberUtils.isIntegerString(`${valueFromJson}`);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/JavaStringMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaString } from "../../java-wrappers/JavaString";
import { MarshallingContext } from "../MarshallingContext";
import { NullableMarshaller } from "./NullableMarshaller";
import { UnmarshallingContext } from "../UnmarshallingContext";
import { instanceOfString } from "../../util/TypeUtils";
export class JavaStringMarshaller extends NullableMarshaller {
public notNullMarshall(input: JavaString, ctx: MarshallingContext): string {
return input.get();
}
public notNullUnmarshall(input: string | JavaString, ctx: UnmarshallingContext): string {
if (instanceOfString(input)) {
return input;
}
return input.get();
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/NullableMarshaller.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../MarshallingContext";
import { Marshaller } from "../Marshaller";
import { Portable } from "../Portable";
import { UnmarshallingContext } from "../UnmarshallingContext";
export abstract class NullableMarshaller, U, V, X> implements Marshaller {
public marshall(input: T, ctx: MarshallingContext): U | null {
if (input === null || input === undefined) {
return null;
}
return this.notNullMarshall(input, ctx);
}
public unmarshall(input: V | undefined, ctx: UnmarshallingContext): X | undefined {
if (input === null || input === undefined) {
return undefined;
}
return this.notNullUnmarshall(input, ctx);
}
public abstract notNullMarshall(input: T, ctx: MarshallingContext): U;
public abstract notNullUnmarshall(input: V, ctx: UnmarshallingContext): X;
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/DefaultMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaEnum,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../../java-wrappers";
import { DefaultMarshaller } from "../DefaultMarshaller";
import { MarshallingContext } from "../../MarshallingContext";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { MarshallerProvider } from "../../MarshallerProvider";
import { Portable } from "../../Portable";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
import { NumberUtils } from "../../../util/NumberUtils";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { EnumStringValueBasedErraiObject } from "../../model/EnumStringValueBasedErraiObject";
beforeEach(() => {
MarshallerProvider.initialize();
});
describe("marshall", () => {
const objectId = ErraiObjectConstants.OBJECT_ID;
const encodedType = ErraiObjectConstants.ENCODED_TYPE;
const value = ErraiObjectConstants.VALUE;
const enumStringValue = ErraiObjectConstants.ENUM_STRING_VALUE;
describe("pojo marshalling", () => {
test("custom pojo, should return serialize it normally", () => {
const input = new User({
name: "my name",
sendSpam: false,
age: new JavaInteger("10"),
address: new Address({
line1: "address line 1",
type: AddressType.WORK
}),
bestFriend: new User({
name: "my name 2",
sendSpam: true,
address: new Address({
line1: "address 2 line 1"
})
})
});
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
name: "my name",
age: 10,
sendSpam: false,
address: {
[encodedType]: "com.app.my.Address",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
line1: "address line 1",
type: new EnumStringValueBasedErraiObject("com.app.my.AddressType", AddressType.WORK.name).asErraiObject()
},
bestFriend: {
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
name: "my name 2",
sendSpam: true,
age: null,
address: {
[encodedType]: "com.app.my.Address",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
line1: "address 2 line 1",
type: null
},
bestFriend: null
}
});
});
test("custom pojo with function, should serialize it normally and ignore the function", () => {
const input = {
_fqcn: "com.app.my.Pojo",
foo: "bar",
doSomething: () => {
return "hey!";
}
};
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "bar"
});
});
test("custom pojo without fqcn, should throw error", () => {
const input = {
foo: "bar"
};
const context = new MarshallingContext();
const marshaller = new DefaultMarshaller();
expect(() => marshaller.marshall(input, context)).toThrowError();
});
test("custom pojo with a pojo without fqcn as property, should throw error", () => {
const input = {
_fqcn: "com.app.my.Pojo",
name: "my name",
childPojo: {
foo: "bar"
}
};
const context = new MarshallingContext();
const marshaller = new DefaultMarshaller();
expect(() => marshaller.marshall(input, context)).toThrowError();
});
test("custom pojo with java types, should serialize it normally", () => {
const date = new Date();
const input = new JavaTypesPojo({
bigDecimal: new JavaBigDecimal("1.1"),
bigInteger: new JavaBigInteger("2"),
boolean: false,
byte: new JavaByte("3"),
double: new JavaDouble("1.2"),
float: new JavaFloat("1.3"),
integer: new JavaInteger("4"),
long: new JavaLong("5"),
short: new JavaShort("6"),
string: "str",
date: new Date(date),
optional: new JavaOptional("optstr")
});
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
bigDecimal: {
[encodedType]: JavaType.BIG_DECIMAL,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "1.1"
},
bigInteger: {
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "2"
},
boolean: false,
byte: 3,
double: 1.2,
float: 1.3,
integer: 4,
long: new NumValBasedErraiObject(JavaType.LONG, "5").asErraiObject(),
short: 6,
string: "str",
date: new ValueBasedErraiObject(JavaType.DATE, `${date.getTime()}`).asErraiObject(),
optional: new ValueBasedErraiObject(JavaType.OPTIONAL, "optstr").asErraiObject()
});
});
test("custom pojo with collection type, should serialize it normally", () => {
const input = {
_fqcn: "com.app.my.Pojo",
list: ["1", "2", "3"],
set: new Set(["3", "2", "1"]),
map: new Map([["k1", "v1"], ["k2", "v2"]])
};
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
list: {
[encodedType]: JavaType.ARRAY_LIST,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: ["1", "2", "3"]
},
set: {
[encodedType]: JavaType.HASH_SET,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: ["3", "2", "1"]
},
map: {
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
k1: "v1",
k2: "v2"
}
}
});
});
test("custom pojo with enum type, should serialize it normally", () => {
const input = {
_fqcn: "com.app.my.Pojo",
str: "foo",
enum: AddressType.HOME
};
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: "com.app.my.Pojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
str: "foo",
enum: new EnumStringValueBasedErraiObject("com.app.my.AddressType", AddressType.HOME.name).asErraiObject()
});
});
});
describe("object caching", () => {
test("custom pojo with repeated pojo objects, should cache the object and don't repeat data", () => {
// === scenario
// repeatedNode appears two times in the hierarchy, all other nodes are unique
const repeatedNode = new Node({ data: "repeatedNode" });
const input = new Node({
data: "root",
right: new Node({ data: "rightNode", left: repeatedNode, right: new Node({ data: "rightLeaf" }) }),
left: repeatedNode
});
// === test
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
// === assertion
// expects all nodes to contain their data and a unique objectId, except for the deepest left node.
// the deepest left node should contain only its encodedType and objectId, which needs to be the same as the root's left node
const rootObjId = output![objectId];
expect(output![encodedType]).toEqual("com.app.my.Node");
expect((output as any).data).toEqual("root");
const firstLeftLeaf = (output as any).left;
const firstLeftLeafObjId = firstLeftLeaf[objectId];
expect(firstLeftLeaf.data).toEqual("repeatedNode");
const rightNodeOut = (output as any).right;
const rightNodeObjId = rightNodeOut[objectId];
expect(rightNodeOut.data).toEqual("rightNode");
const repeatedLeftLeaf = (rightNodeOut as any).left;
const repeatedLeftLeafObjId = repeatedLeftLeaf[objectId];
expect(repeatedLeftLeaf.data).toBeUndefined();
const rightLeafOut = (rightNodeOut as any).right;
const rightLeafObjId = rightLeafOut[objectId];
expect(rightLeafOut.data).toEqual("rightLeaf");
expect(firstLeftLeafObjId).toEqual(repeatedLeftLeafObjId); // reuse same id
const allObjIds = [rootObjId, firstLeftLeafObjId, rightNodeObjId, repeatedLeftLeafObjId, rightLeafObjId];
expect(allObjIds.forEach(id => expect(id).toMatch(NumberUtils.nonNegativeIntegerRegex)));
// all ids unique (excluding the reused one)
const uniqueObjIds = new Set(allObjIds);
expect(uniqueObjIds).toStrictEqual(new Set([rootObjId, firstLeftLeafObjId, rightNodeObjId, rightLeafObjId]));
});
test("custom pojo with repeated JavaBigDecimal objects, should not cache it and not reuse data", () => {
const repeatedValue = new JavaBigDecimal("1.1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaBigDecimal("1.2") }),
right: new Node({ data: repeatedValue })
});
// === test
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data[value]).toEqual("1.1");
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data[value]).toEqual("1.2");
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data[value]).toEqual("1.1");
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// create new object ids even for same obj references
expect(new Set(allObjectIds)).toStrictEqual(new Set(allObjectIds));
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaBigInteger objects, should not cache it", () => {
const repeatedValue = new JavaBigInteger("1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaBigInteger("2") }),
right: new Node({ data: repeatedValue })
});
// === test
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data[value]).toEqual("1");
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data[value]).toEqual("2");
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data[value]).toEqual("1");
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// create new object ids even for same obj references
expect(new Set(allObjectIds)).toStrictEqual(new Set(allObjectIds));
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaBoolean objects, should not cache it", () => {
const repeatedValue = new JavaBoolean(false);
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaBoolean(true) }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Boolean types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaByte objects, should not cache it", () => {
const repeatedValue = new JavaByte("1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaByte("2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Byte types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated array objects, should cache the object and don't repeat data", () => {
const repeatedValue = ["a", "b", "c"];
const arrayInput = new Node({
data: repeatedValue,
left: new Node({ data: ["d", "e"] }),
right: new Node({ data: repeatedValue })
});
const javaArrayListInput = new Node({
data: new JavaArrayList(repeatedValue),
left: new Node({ data: new JavaArrayList(["d", "e"]) }),
right: new Node({ data: new JavaArrayList(repeatedValue) })
});
[arrayInput, javaArrayListInput].forEach(input => {
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data).toStrictEqual({
[encodedType]: JavaType.ARRAY_LIST,
[objectId]: expect.anything(),
[value]: ["a", "b", "c"]
});
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data).toStrictEqual({
[encodedType]: JavaType.ARRAY_LIST,
[objectId]: expect.anything(),
[value]: ["d", "e"]
});
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data).toStrictEqual({
[encodedType]: JavaType.ARRAY_LIST,
[objectId]: expect.anything()
// missing value since it is cached
});
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// all ids are unique except for the right data id, that was reused
expect(new Set(allObjectIds)).toStrictEqual(
new Set([rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId])
);
// do not cache repeated object
const cached = context.getCached(repeatedValue);
expect(ValueBasedErraiObject.from(cached!)).toStrictEqual(
new ValueBasedErraiObject(JavaType.ARRAY_LIST, undefined, rootDataObjId)
);
});
});
test("custom pojo with repeated set objects, should cache the object and don't repeat data", () => {
const repeatedValue = new Set(["a", "b", "c"]);
const setInput = new Node({
data: repeatedValue,
left: new Node({ data: new Set(["d", "e"]) }),
right: new Node({ data: repeatedValue })
});
const javaHashSetInput = new Node({
data: new JavaHashSet(repeatedValue),
left: new Node({ data: new JavaHashSet(new Set(["d", "e"])) }),
right: new Node({ data: new JavaHashSet(repeatedValue) })
});
[setInput, javaHashSetInput].forEach(input => {
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data).toStrictEqual({
[encodedType]: JavaType.HASH_SET,
[objectId]: expect.anything(),
[value]: ["a", "b", "c"]
});
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data).toStrictEqual({
[encodedType]: JavaType.HASH_SET,
[objectId]: expect.anything(),
[value]: ["d", "e"]
});
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data).toStrictEqual({
[encodedType]: JavaType.HASH_SET,
[objectId]: expect.anything()
// missing value since it is cached
});
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// all ids are unique except for the right data id, that was reused
expect(new Set(allObjectIds)).toStrictEqual(
new Set([rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId])
);
// do not cache repeated object
const cached = context.getCached(repeatedValue);
expect(ValueBasedErraiObject.from(cached!)).toStrictEqual(
new ValueBasedErraiObject(JavaType.HASH_SET, undefined, rootDataObjId)
);
});
});
test("custom pojo with repeated map objects, should cache the object and don't repeat data", () => {
const repeatedMap = new Map([["k1", "v1"]]);
const mapInput = new Node({
data: repeatedMap,
left: new Node({ data: new Map([["k2", "v2"]]) }),
right: new Node({ data: repeatedMap })
});
const javaHashMapInput = new Node({
data: new JavaHashMap(repeatedMap),
left: new Node({ data: new JavaHashMap(new Map([["k2", "v2"]])) }),
right: new Node({ data: new JavaHashMap(repeatedMap) })
});
[mapInput, javaHashMapInput].forEach(input => {
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.anything(),
[value]: {
k1: "v1"
}
});
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.anything(),
[value]: {
k2: "v2"
}
});
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.anything()
// missing value since it is cached
});
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// all ids are unique except for the right data id, that was reused
expect(new Set(allObjectIds)).toStrictEqual(
new Set([rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId])
);
// do not cache repeated object's data
const cached = context.getCached(repeatedMap);
expect(ValueBasedErraiObject.from(cached!)).toStrictEqual(
new ValueBasedErraiObject(JavaType.HASH_MAP, undefined, rootDataObjId)
);
});
});
test("custom pojo with repeated JavaDouble objects, should not cache it", () => {
const repeatedValue = new JavaDouble("1.1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaDouble("1.2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Double types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaFloat objects, should not cache it", () => {
const repeatedValue = new JavaFloat("1.1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaFloat("1.2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Float types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaInteger objects, should not cache it", () => {
const repeatedValue = new JavaInteger("1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaInteger("2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Integer types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaLong objects, should not cache it", () => {
const repeatedValue = new JavaLong("1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaLong("2") }),
right: new Node({ data: repeatedValue })
});
// === test
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootData = NumValBasedErraiObject.from((output as any).data);
expect(rootData.numVal).toEqual("1");
const leftObj = NumValBasedErraiObject.from((output as any).left);
const leftData = NumValBasedErraiObject.from((output as any).left.data);
expect(leftData.numVal).toEqual("2");
const rightObj = NumValBasedErraiObject.from((output as any).right);
const rightData = NumValBasedErraiObject.from((output as any).right.data);
expect(rightData.numVal).toEqual("1");
const allObjectIds = [rootObjId, rootData.objId, leftObj.objId, leftData.objId, rightObj.objId, rightData.objId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// create new object ids even for same obj references
expect(new Set(allObjectIds)).toStrictEqual(new Set(allObjectIds));
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaShort objects, should not cache it", () => {
const repeatedValue = new JavaShort("1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaShort("2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because Short types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaString objects, should not cache it", () => {
const repeatedValue = new JavaString("str1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaString("str2") }),
right: new Node({ data: repeatedValue })
});
const context = new MarshallingContext();
new DefaultMarshaller().marshall(input, context);
// in this test we're not interested in the output structure, because String types are not wrapped into an
// ErraiObject, so, it doesn't even have an objectId assigned.
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaOptional objects, should not cache it", () => {
const repeatedValue = new JavaOptional("str1");
const input = new Node({
data: repeatedValue,
left: new Node({ data: new JavaOptional("str2") }),
right: new Node({ data: repeatedValue })
});
// === test
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data[value]).toStrictEqual("str1");
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data[value]).toEqual("str2");
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data[value]).toEqual("str1");
const allObjectIds = [rootObjId, rootDataObjId, leftObjId, leftDataObjId, rightObjId, rightDataObjId];
allObjectIds.forEach(id => expect(id).toBeDefined());
// optional objects always use the same object id (its value doesn't matter)
expect(new Set(allObjectIds)).toStrictEqual(new Set([rootObjId, rootDataObjId, leftObjId, rightObjId]));
expect(rootDataObjId).toEqual(leftDataObjId);
expect(rootDataObjId).toEqual(rightDataObjId);
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
test("custom pojo with repeated JavaEnum objects, should not cache it", () => {
const repeatedValue = AddressType.WORK;
const input = new Node({
data: repeatedValue,
left: new Node({ data: AddressType.HOME }),
right: new Node({ data: repeatedValue })
});
// === test
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context);
// === assertions
const rootObjId = output![objectId];
const rootDataObjId = (output as any).data[objectId];
expect((output as any).data[enumStringValue]).toStrictEqual(AddressType.WORK.name);
const leftObjId = (output as any).left[objectId];
const leftDataObjId = (output as any).left.data[objectId];
expect((output as any).left.data[enumStringValue]).toEqual(AddressType.HOME.name);
const rightObjId = (output as any).right[objectId];
const rightDataObjId = (output as any).right.data[objectId];
expect((output as any).right.data[enumStringValue]).toEqual(AddressType.WORK.name);
// every Node object has an unique id
expect(new Set([rootObjId, leftObjId, rightObjId])).toStrictEqual(new Set([rootObjId, leftObjId, rightObjId]));
// every enum field doesn't have an object id defined
[rootDataObjId, rightDataObjId, leftDataObjId].forEach(id => expect(id).toBeUndefined());
// do not cache repeated object
expect(context.getCached(repeatedValue)).toBeUndefined();
});
});
describe("non-pojo root types", () => {
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root JavaBigDecimal object, should serialize it normally", () => {
const input = new JavaBigDecimal("1.2");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.BIG_DECIMAL,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "1.2"
});
});
test("root JavaBigInteger object, should serialize it normally", () => {
const input = new JavaBigInteger("1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "1"
});
});
test("root JavaByte object, should serialize it to byte raw value", () => {
const input = new JavaByte("1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(1);
});
test("root JavaDouble object, should serialize it to double raw value", () => {
const input = new JavaDouble("1.1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(1.1);
});
test("root JavaFloat object, should serialize it to float raw value", () => {
const input = new JavaFloat("1.1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(1.1);
});
test("root JavaInteger object, should serialize it to integer raw value", () => {
const input = new JavaInteger("1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(1);
});
test("root JavaLong object, should serialize it normally", () => {
const input = new JavaLong("1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.LONG, "1").asErraiObject());
});
test("root JavaShort object, should serialize it normally to short raw value", () => {
const input = new JavaShort("1");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(1);
});
test("root JavaOptional object, should serialize it normally", () => {
const input = new JavaOptional("str");
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(new ValueBasedErraiObject(JavaType.OPTIONAL, "str").asErraiObject());
});
test("root JavaEnum object, should serialize it normally", () => {
const input = AddressType.WORK;
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(
new EnumStringValueBasedErraiObject(AddressType.__fqcn(), AddressType.WORK.name).asErraiObject()
);
});
test("root string object, should serialize it to string raw value", () => {
const stringInput = "str";
const javaStringInput = new JavaString("str");
[stringInput, javaStringInput].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual("str");
});
});
test("root date object, should serialize it normally", () => {
const date = new Date();
const javaDate = new JavaDate(date);
[date, javaDate].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(new ValueBasedErraiObject(JavaType.DATE, `${date.getTime()}`).asErraiObject());
});
});
test("root boolean object, should serialize it to boolean raw value", () => {
const booleanInput = false;
const javaBooleanInput = new JavaBoolean(false);
[booleanInput, javaBooleanInput].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toEqual(false);
});
});
test("root number object, should throw error", () => {
const input = 125.1;
const marshaller = new DefaultMarshaller();
const ctx = new MarshallingContext();
expect(() => marshaller.marshall(input, ctx)).toThrowError();
});
test("root array object, should serialize it normally", () => {
const arrayInput = ["1", "2", "3"];
const javaArrayListInput = new JavaArrayList(["1", "2", "3"]);
[arrayInput, javaArrayListInput].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.ARRAY_LIST,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: ["1", "2", "3"]
});
});
});
test("root set object, should serialize it normally", () => {
const setInput = new Set(["1", "2", "3"]);
const javaHashSetInput = new JavaHashSet(new Set(["1", "2", "3"]));
[setInput, javaHashSetInput].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_SET,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: ["1", "2", "3"]
});
});
});
test("root map object, should serialize it normally", () => {
const mapInput = new Map([["k1", "v1"], ["k2", "v2"]]);
const javaHashMapInput = new JavaHashMap(new Map([["k1", "v1"], ["k2", "v2"]]));
[mapInput, javaHashMapInput].forEach(input => {
const output = new DefaultMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
k1: "v1",
k2: "v2"
}
});
});
});
});
class Node implements Portable {
private readonly _fqcn = "com.app.my.Node";
public readonly data?: any = undefined;
public readonly left?: Node = undefined;
public readonly right?: Node = undefined;
constructor(self: { data?: any; left?: Node; right?: Node }) {
Object.assign(this, self);
}
}
});
describe("unmarshall", () => {
describe("non-pojo root types", () => {
test("root null object, should unmarshall to undefined", () => {
const marshaller = new DefaultMarshaller();
const input = null as any;
const marshalledInput = marshaller.marshall(input, new MarshallingContext()) as any;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
test("root undefined object, should unmarshall to null", () => {
const marshaller = new DefaultMarshaller();
const input = undefined as any;
const marshalledInput = marshaller.marshall(input, new MarshallingContext()) as any;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
test("root JavaBigDecimal object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = new JavaBigDecimal("1.1");
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaBigDecimal("1.1"));
});
test("root JavaBigInteger object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = new JavaBigInteger("1");
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaBigInteger("1"));
});
test("root JavaByte object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaByte("1"));
});
test("root JavaDouble object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = 1.1;
const marshalledInput = new NumValBasedErraiObject(JavaType.DOUBLE, input).asErraiObject();
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaDouble("1.1"));
});
test("root JavaFloat object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = 1.1;
const marshalledInput = new NumValBasedErraiObject(JavaType.FLOAT, input).asErraiObject();
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaFloat("1.1"));
});
test("root JavaInteger object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaInteger("1"));
});
test("root JavaLong object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = new JavaLong("1");
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaLong("1"));
});
test("root JavaShort object, should unmarshall it normally", () => {
const marshaller = new DefaultMarshaller();
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaShort("1"));
});
test("root JavaOptional object, should serialize it normally", () => {
const marshaller = new DefaultMarshaller();
const input = new JavaOptional("1");
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional("1"));
});
test("root JavaEnum object, should serialize it normally", () => {
const marshaller = new DefaultMarshaller();
const input = AddressType.WORK;
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const factory = new Map([
[
"com.app.my.AddressType",
((name: string) => {
switch (name) {
case "HOME":
return AddressType.HOME;
case "WORK":
return AddressType.WORK;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
]);
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(factory));
expect(output).toStrictEqual(AddressType.WORK);
});
test("root string object, should unmarshall it to native string", () => {
const marshaller = new DefaultMarshaller();
const stringInput = "foo";
const javaStringInput = new JavaString("foo");
[stringInput, javaStringInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual("foo");
});
});
test("root date object, should unmarshall it to native date", () => {
const marshaller = new DefaultMarshaller();
const baseDate = new Date();
const dateInput = new Date(baseDate);
const javaDateInput = new JavaDate(new Date(baseDate));
[dateInput, javaDateInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(baseDate);
});
});
test("root boolean object, should unmarshall it to native boolean", () => {
const marshaller = new DefaultMarshaller();
const booleanInput = false;
const javaBooleanInput = new JavaBoolean(false);
[booleanInput, javaBooleanInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(false);
});
});
test("root array object, should unmarshall it to native array", () => {
const marshaller = new DefaultMarshaller();
const arrayInput = ["foo"];
const javaArrayInput = new JavaArrayList(["foo"]);
[arrayInput, javaArrayInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(["foo"]);
});
});
test("root set object, should unmarshall it to native set", () => {
const marshaller = new DefaultMarshaller();
const setInput = new Set(["foo"]);
const javaSetInput = new JavaHashSet(new Set(["foo"]));
[setInput, javaSetInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Set(["foo"]));
});
});
test("root map object, should unmarshall it native map", () => {
const marshaller = new DefaultMarshaller();
const mapInput = new Map([["foo", "bar"]]);
const javaMapInput = new JavaHashMap(new Map([["foo", "bar"]]));
[mapInput, javaMapInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([["foo", "bar"]]));
});
});
test("root integer number object, should throw error", () => {
const marshaller = new DefaultMarshaller();
const input = 1;
expect(() => marshaller.unmarshall(input as any, new UnmarshallingContext(new Map()))).toThrowError();
});
test("root float number object, should throw error", () => {
const marshaller = new DefaultMarshaller();
const input = 1.1;
expect(() => marshaller.unmarshall(input as any, new UnmarshallingContext(new Map()))).toThrowError();
});
});
describe("pojo root types", () => {
test("with custom pojo, should unmarshall correctly", () => {
const oracle = new Map([
["com.app.my.Pojo", () => new User({ age: new JavaInteger("0") }) as any],
["com.app.my.Address", () => new Address({} as any) as any],
[
"com.app.my.AddressType",
((name: string) => {
switch (name) {
case "HOME":
return AddressType.HOME;
case "WORK":
return AddressType.WORK;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
]);
const marshaller = new DefaultMarshaller();
const input = new User({
name: "my name",
sendSpam: false,
age: new JavaInteger("10"),
address: new Address({
line1: "address line 1",
type: AddressType.HOME
}),
bestFriend: new User({
name: "my name 2",
sendSpam: true,
address: new Address({
line1: "address 2 line 1"
})
})
});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle));
expect(output).toEqual(input);
});
test("with custom pojo with function, should unmarshall to a correct object containing the function", () => {
const oracle = new Map([["com.app.my.PojoWithFunction", () => new PojoWithFunction({})]]);
const marshaller = new DefaultMarshaller();
const input = new PojoWithFunction({ foo: "bar" });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle)) as PojoWithFunction;
expect(output).toEqual(input);
// generates a full functional object of the correct type
expect(output.whatToSay()).toEqual("Hello, bar!");
});
test("with custom pojo with java types, should unmarshall normally", () => {
const marshaller = new DefaultMarshaller();
const oracle = new Map([
[
"com.app.my.Pojo",
() =>
new JavaTypesPojo({
bigDecimal: new JavaBigDecimal("0"),
bigInteger: new JavaBigInteger("0"),
byte: new JavaByte("0"),
double: new JavaDouble("0"),
float: new JavaFloat("0"),
integer: new JavaInteger("0"),
short: new JavaShort("0")
})
]
]);
const input = new JavaTypesPojo({
bigDecimal: new JavaBigDecimal("1.1"),
bigInteger: new JavaBigInteger("2"),
boolean: false,
byte: new JavaByte("3"),
double: new JavaDouble("1.2"),
float: new JavaFloat("1.3"),
integer: new JavaInteger("4"),
long: new JavaLong("5"),
short: new JavaShort("6"),
string: "str",
date: new Date(),
optional: new JavaOptional("optstr")
});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle));
expect(output).toEqual(input);
});
test("with custom pojo with java collection types, should unmarshall normally", () => {
const marshaller = new DefaultMarshaller();
const oracle = new Map([["com.app.my.JavaCollectionTypesPojo", () => new JavaCollectionTypesPojo({})]]);
const input = new JavaCollectionTypesPojo({
list: ["1", "2"],
set: new Set(["3", "2"]),
map: new Map([["k1", "v1"], ["k2", "v2"]])
});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle));
expect(output).toEqual(input);
});
test("with custom pojo without fqcn, should throw error", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.Pojo", () => new User({ age: new JavaInteger("0") })]])
);
const input = new User({});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
// remove its fqcn
delete marshalledInput[ErraiObjectConstants.ENCODED_TYPE];
expect(() => marshaller.unmarshall(marshalledInput, unmarshallContext)).toThrowError();
});
test("with custom pojo without factory, should throw error", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(new Map());
const input = new User({});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
expect(() => marshaller.unmarshall(marshalledInput, unmarshallContext)).toThrowError();
});
test("with custom pojo with property without fqcn, should throw error", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
["com.app.my.Pojo", () => new User({ age: new JavaInteger("0") }) as any],
["com.app.my.Address", () => new Address({} as any) as any]
])
);
const input = new User({ name: "foo", address: new Address({ line1: "bla" }) });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
// remove its fqcn
delete (marshalledInput as any).address[ErraiObjectConstants.ENCODED_TYPE];
expect(() => marshaller.unmarshall(marshalledInput, unmarshallContext)).toThrowError();
});
class PojoWithFunction implements Portable {
private readonly _fqcn = "com.app.my.PojoWithFunction";
public readonly foo?: string = undefined;
constructor(self: { foo?: string }) {
Object.assign(this, self);
}
public whatToSay() {
return `Hello, ${this.foo}!`;
}
}
class JavaCollectionTypesPojo implements Portable {
private readonly _fqcn = "com.app.my.JavaCollectionTypesPojo";
public readonly list?: string[] = undefined;
public readonly set?: Set = undefined;
public readonly map?: Map = undefined;
constructor(self: { list?: string[]; set?: Set; map?: Map }) {
Object.assign(this, self);
}
}
});
describe("object caching", () => {
test("custom pojo with repeated pojo objects, should cache the object and reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
["com.app.my.Address", () => new Address({}) as any],
["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]
])
);
const repeatedObject = new Address({ line1: "bla address" });
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).toBe(output.field2!);
});
test("custom pojo with repeated JavaBigDecimal objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new JavaBigDecimal("1.1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaBigInteger objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new JavaBigInteger("1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaByte objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
[
"com.app.my.RepeatedFieldsPojo",
() => new RepeatedFieldsPojo({ field1: new JavaByte("0"), field2: new JavaByte("0") }) as any
]
])
);
const repeatedObject = new JavaByte("1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaDouble objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
[
"com.app.my.RepeatedFieldsPojo",
() => new RepeatedFieldsPojo({ field1: new JavaDouble("0"), field2: new JavaDouble("0") }) as any
]
])
);
const repeatedObject = new JavaDouble("1.1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaFloat objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
[
"com.app.my.RepeatedFieldsPojo",
() => new RepeatedFieldsPojo({ field1: new JavaFloat("0"), field2: new JavaFloat("0") }) as any
]
])
);
const repeatedObject = new JavaFloat("1.1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaInteger objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
[
"com.app.my.RepeatedFieldsPojo",
() => new RepeatedFieldsPojo({ field1: new JavaInteger("0"), field2: new JavaInteger("0") }) as any
]
])
);
const repeatedObject = new JavaInteger("1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaLong objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new JavaLong("1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaShort objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
[
"com.app.my.RepeatedFieldsPojo",
() => new RepeatedFieldsPojo({ field1: new JavaShort("0"), field2: new JavaShort("0") }) as any
]
])
);
const repeatedObject = new JavaShort("1");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaOptional objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new JavaOptional("foo");
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo<
JavaOptional
>;
expect(output).toEqual(input);
expect(output.field1!).not.toBe(output.field2!);
});
test("custom pojo with repeated JavaEnum objects, should not cache it and don't reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([
["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any],
[
"com.app.my.AddressType",
((name: string) => {
switch (name) {
case "HOME":
return AddressType.HOME;
case "WORK":
return AddressType.WORK;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
])
);
const repeatedObject = AddressType.HOME;
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).toBe(output.field2!);
});
test("custom pojo with repeated array objects, should cache the object and reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedInlineArray = ["foo", "bar"];
const inlineArrayInput = new RepeatedFieldsPojo({ field1: repeatedInlineArray, field2: repeatedInlineArray });
const repeatedNewArray = new Array("foo", "bar");
const newArrayInput = new RepeatedFieldsPojo({ field1: repeatedNewArray, field2: repeatedNewArray });
[inlineArrayInput, newArrayInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo;
expect(output).toEqual(input);
expect(output.field1!).toBe(output.field2!);
});
});
test("custom pojo with repeated set objects, should cache the object and reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new Set(["foo", "bar"]);
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo>;
expect(output).toEqual(input);
expect(output.field1!).toBe(output.field2!);
});
test("custom pojo with repeated map objects, should cache the object and reuse data", () => {
const marshaller = new DefaultMarshaller();
const unmarshallContext = new UnmarshallingContext(
new Map([["com.app.my.RepeatedFieldsPojo", () => new RepeatedFieldsPojo({}) as any]])
);
const repeatedObject = new Map([["foo1", "bar1"], ["foo2", "bar2"]]);
const input = new RepeatedFieldsPojo({ field1: repeatedObject, field2: repeatedObject });
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, unmarshallContext) as RepeatedFieldsPojo<
Map
>;
expect(output).toEqual(input);
expect(output.field1!).toBe(output.field2!);
});
class RepeatedFieldsPojo implements Portable> {
private readonly _fqcn = "com.app.my.RepeatedFieldsPojo";
public field1?: T = undefined;
public field2?: T = undefined;
constructor(self: { field1?: T; field2?: T }) {
Object.assign(this, self);
}
}
});
});
class User implements Portable {
private readonly _fqcn = "com.app.my.Pojo";
public readonly name?: string = undefined;
public readonly sendSpam?: boolean = undefined;
public readonly age?: JavaInteger = undefined;
public readonly address?: Address = undefined;
public readonly bestFriend?: User = undefined;
constructor(self: { name?: string; sendSpam?: boolean; age?: JavaInteger; address?: Address; bestFriend?: User }) {
Object.assign(this, self);
}
}
class Address implements Portable {
private readonly _fqcn = "com.app.my.Address";
public line1?: string = undefined;
public type?: AddressType = undefined;
constructor(self: { line1?: string; type?: AddressType }) {
Object.assign(this, self);
}
}
class AddressType extends JavaEnum {
public static readonly HOME: AddressType = new AddressType("HOME");
public static readonly WORK: AddressType = new AddressType("WORK");
protected readonly _fqcn: string = AddressType.__fqcn();
public static __fqcn(): string {
return "com.app.my.AddressType";
}
public static values() {
return [AddressType.HOME, AddressType.WORK];
}
}
class JavaTypesPojo implements Portable {
private readonly _fqcn = "com.app.my.Pojo";
public readonly bigDecimal?: JavaBigDecimal = undefined;
public readonly bigInteger?: JavaBigInteger = undefined;
public readonly boolean?: boolean = undefined;
public readonly byte?: JavaByte = undefined;
public readonly double?: JavaDouble = undefined;
public readonly float?: JavaFloat = undefined;
public readonly integer?: JavaInteger = undefined;
public readonly long?: JavaLong = undefined;
public readonly short?: JavaShort = undefined;
public readonly string?: string = undefined;
public readonly date?: Date = undefined;
public readonly optional?: JavaOptional = undefined;
constructor(self: {
bigDecimal?: JavaBigDecimal;
bigInteger?: JavaBigInteger;
boolean?: boolean;
byte?: JavaByte;
double?: JavaDouble;
float?: JavaFloat;
integer?: JavaInteger;
long?: JavaLong;
short?: JavaShort;
string?: string;
date?: Date;
optional?: JavaOptional;
}) {
Object.assign(this, self);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaBigDecimalMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaBigDecimal } from "../../../java-wrappers";
import { JavaBigDecimalMarshaller } from "../JavaBigDecimalMarshaller";
import { MarshallingContext } from "../../MarshallingContext";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaType } from "../../../java-wrappers/JavaType";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { NumberUtils } from "../../../util/NumberUtils";
describe("marshall", () => {
test("with regular big decimal, should serialize it normally", () => {
const input = new JavaBigDecimal("12.12");
const output = new JavaBigDecimalMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: JavaType.BIG_DECIMAL,
[ErraiObjectConstants.OBJECT_ID]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[ErraiObjectConstants.VALUE]: "12.12"
});
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaBigDecimalMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaBigDecimalMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with regular input, should return a JavaBigDecimal instance", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const input = new JavaBigDecimal("125.2");
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output.get().toString(10)).toEqual(input.get().toString(10));
});
test("with non string value, should throw error", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_DECIMAL, false, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with non numeric string value, should throw error", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_DECIMAL, "abc", "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should return a JavaBigDecimal instance containing NaN", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_DECIMAL, null, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should return a JavaBigDecimal instance containing NaN", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_DECIMAL, undefined, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with empty string value, should return a JavaBigDecimal instance containing NaN", () => {
const marshaller = new JavaBigDecimalMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_DECIMAL, "", "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaBigIntegerMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { JavaBigInteger } from "../../../java-wrappers";
import { JavaBigIntegerMarshaller } from "../JavaBigIntegerMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaType } from "../../../java-wrappers/JavaType";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { NumberUtils } from "../../../util/NumberUtils";
describe("marshall", () => {
test("with regular big integer, should serialize it normally", () => {
const input = new JavaBigInteger("12");
const output = new JavaBigIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: JavaType.BIG_INTEGER,
[ErraiObjectConstants.OBJECT_ID]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[ErraiObjectConstants.VALUE]: "12"
});
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaBigIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaBigIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with regular input, should return a JavaBigInteger instance", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = new JavaBigInteger("125");
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output.get().toString(10)).toEqual(input.get().toString(10));
});
test("with non string value, should return a JavaBigInteger instance containing NaN", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_INTEGER, false, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with non numeric string value, should throw error", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_INTEGER, "abc", "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should return a JavaBigInteger instance containing NaN", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_INTEGER, null, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should return a JavaBigInteger instance containing NaN", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_INTEGER, undefined, "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with empty string value, should return a JavaBigInteger instance containing NaN", () => {
const marshaller = new JavaBigIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const marshalledInput = new ValueBasedErraiObject(JavaType.BIG_INTEGER, "", "1").asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaBooleanMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaBoolean } from "../../../java-wrappers";
import { JavaBooleanMarshaller } from "../JavaBooleanMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaType } from "../../../java-wrappers/JavaType";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
describe("marshall", () => {
test("with regular boolean, should return the same value", () => {
const input = new JavaBoolean(false);
const output = new JavaBooleanMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(false);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaBooleanMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaBooleanMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with boolean input, should return a boolean instance", () => {
const marshaller = new JavaBooleanMarshaller();
const context = new UnmarshallingContext(new Map());
const input = true;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toBeTruthy();
});
test("with ErraiObject regular input, should return a boolean instance", () => {
const marshaller = new JavaBooleanMarshaller();
const context = new UnmarshallingContext(new Map());
const input = false;
const marshalledInput = new NumValBasedErraiObject(JavaType.BOOLEAN, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toBeFalsy();
});
test("with non boolean value, should throw error", () => {
const marshaller = new JavaBooleanMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BOOLEAN, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaBooleanMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BOOLEAN, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaBooleanMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BOOLEAN, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaByteMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaByte } from "../../../java-wrappers";
import { JavaByteMarshaller } from "../JavaByteMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
test("with regular byte, should return same value", () => {
const input = new JavaByte("2");
const output = new JavaByteMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(2);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaByteMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaByteMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
describe("number input", () => {
test("with byte, should return a JavaByte instance", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toEqual(new JavaByte("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
});
describe("ErraiObject input", () => {
test("with byte, should return a JavaByte instance", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(new JavaByte("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaByteMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.BYTE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaCollectionSubTypesMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { JavaArrayListMarshaller, JavaHashSetMarshaller } from "../JavaCollectionMarshaller";
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../../java-wrappers";
import { MarshallingContext } from "../../MarshallingContext";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { MarshallerProvider } from "../../MarshallerProvider";
import { JavaBigIntegerMarshaller } from "../JavaBigIntegerMarshaller";
import { Portable } from "../../Portable";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { NumberUtils } from "../../../util/NumberUtils";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
const encodedType = ErraiObjectConstants.ENCODED_TYPE;
const objectId = ErraiObjectConstants.OBJECT_ID;
const value = ErraiObjectConstants.VALUE;
let context: MarshallingContext;
beforeEach(() => {
MarshallerProvider.initialize();
context = new MarshallingContext();
});
test("with empty collection, should serialize normally", () => {
const arrayListScenario = () => {
const input = new JavaArrayList([]);
return { fqcn: JavaType.ARRAY_LIST, output: new JavaArrayListMarshaller().marshall(input, context) };
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set([]));
return { fqcn: JavaType.HASH_SET, output: new JavaHashSetMarshaller().marshall(input, context) };
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: []
});
});
});
test("with JavaNumber collection, should wrap every element into an errai object", () => {
const numberArray = [new JavaInteger("1"), new JavaInteger("2"), new JavaInteger("3")];
const arrayListScenario = () => {
const input = new JavaArrayList(numberArray);
return { fqcn: JavaType.ARRAY_LIST, output: new JavaArrayListMarshaller().marshall(input, context) };
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set(numberArray));
return { fqcn: JavaType.HASH_SET, output: new JavaHashSetMarshaller().marshall(input, context) };
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: [
new NumValBasedErraiObject(JavaType.INTEGER, 1).asErraiObject(),
new NumValBasedErraiObject(JavaType.INTEGER, 2).asErraiObject(),
new NumValBasedErraiObject(JavaType.INTEGER, 3).asErraiObject()
]
});
});
});
test("with JavaBoolean collection, should wrap every element into an errai object", () => {
const booleanArray = [new JavaBoolean(true), new JavaBoolean(false)];
const arrayListScenario = () => {
const input = new JavaArrayList(booleanArray);
return { fqcn: JavaType.ARRAY_LIST, output: new JavaArrayListMarshaller().marshall(input, context) };
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set(booleanArray));
return { fqcn: JavaType.HASH_SET, output: new JavaHashSetMarshaller().marshall(input, context) };
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: [
new NumValBasedErraiObject(JavaType.BOOLEAN, true).asErraiObject(),
new NumValBasedErraiObject(JavaType.BOOLEAN, false).asErraiObject()
]
});
});
});
test("with JavaBigNumber collection, should serialize every element normally", () => {
const bigIntegerMarshaller = new JavaBigIntegerMarshaller();
const bigNumberArray = [new JavaBigInteger("1"), new JavaBigInteger("2"), new JavaBigInteger("3")];
const arrayListScenario = () => {
const input = new JavaArrayList(bigNumberArray);
return { fqcn: JavaType.ARRAY_LIST, output: new JavaArrayListMarshaller().marshall(input, context) };
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set(bigNumberArray));
return { fqcn: JavaType.HASH_SET, output: new JavaHashSetMarshaller().marshall(input, context) };
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: [
{
...(bigIntegerMarshaller.marshall(new JavaBigInteger("1"), context) as any),
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex)
},
{
...(bigIntegerMarshaller.marshall(new JavaBigInteger("2"), context) as any),
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex)
},
{
...(bigIntegerMarshaller.marshall(new JavaBigInteger("3"), context) as any),
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex)
}
]
});
});
});
test("with custom object collection, should serialize every element normally", () => {
const portableArray = [
new MyPortable({ foo: "foo1", bar: "bar1" }),
new MyPortable({ foo: "foo2", bar: "bar2" }),
new MyPortable({ foo: "foo3", bar: "bar3" })
];
const arrayListScenario = () => {
const input = new JavaArrayList(portableArray);
return {
fqcn: JavaType.ARRAY_LIST,
output: new JavaArrayListMarshaller().marshall(input, new MarshallingContext())
};
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set(portableArray));
return {
fqcn: JavaType.HASH_SET,
output: new JavaHashSetMarshaller().marshall(input, new MarshallingContext())
};
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: [
{
[encodedType]: "com.portable.my",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "foo1",
bar: "bar1"
},
{
[encodedType]: "com.portable.my",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "foo2",
bar: "bar2"
},
{
[encodedType]: "com.portable.my",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "foo3",
bar: "bar3"
}
]
});
});
});
test("with collection containing null elements, should serialize every element normally", () => {
const arrayListScenario = () => {
const input = new JavaArrayList([null]);
return {
fqcn: JavaType.ARRAY_LIST,
output: new JavaArrayListMarshaller().marshall(input, new MarshallingContext())
};
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set([null]));
return {
fqcn: JavaType.HASH_SET,
output: new JavaHashSetMarshaller().marshall(input, new MarshallingContext())
};
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
expect(output).toStrictEqual({
[encodedType]: fqcn,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: [null]
});
});
});
test("with custom pojo array containing repeated elements, should cache inner objects and don't repeat data", () => {
const repeatedValue = new Node({ data: "foo1", left: undefined, right: undefined });
const portableArray = [repeatedValue, new Node({ data: "foo2", left: undefined, right: repeatedValue })];
const arrayListScenario = () => {
const input = new JavaArrayList(portableArray);
return {
fqcn: JavaType.ARRAY_LIST,
output: new JavaArrayListMarshaller().marshall(input, new MarshallingContext())
};
};
const hashSetScenario = () => {
const input = new JavaHashSet(new Set(portableArray));
return {
fqcn: JavaType.HASH_SET,
output: new JavaHashSetMarshaller().marshall(input, new MarshallingContext())
};
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const { fqcn, output } = outputFunc();
const rootObjId = output![objectId];
expect(output![encodedType]).toEqual(fqcn);
expect(rootObjId).toMatch(NumberUtils.nonNegativeIntegerRegex);
const rootObjValue = output![value] as any[];
const foo2Objects = rootObjValue.filter(obj => obj.data === "foo2");
expect(foo2Objects.length).toEqual(1);
const uniqueObjId = foo2Objects[0][objectId];
expect(uniqueObjId).toMatch(NumberUtils.nonNegativeIntegerRegex);
const repeatedObjects = rootObjValue.filter(obj => obj.data !== "foo2");
expect(repeatedObjects.length).toEqual(1);
const repeatedObjId = repeatedObjects[0][objectId];
expect(repeatedObjId).toMatch(NumberUtils.nonNegativeIntegerRegex);
expect(rootObjValue).toEqual([
{ [encodedType]: "com.app.my.Node", [objectId]: repeatedObjId, data: "foo1", left: null, right: null },
{
[encodedType]: "com.app.my.Node",
[objectId]: uniqueObjId,
data: "foo2",
right: { [encodedType]: "com.app.my.Node", [objectId]: repeatedObjId },
left: null
}
]);
});
});
test("root null object, should serialize to null", () => {
const input = null as any;
const arrayListScenario = () => {
return new JavaArrayListMarshaller().marshall(input, new MarshallingContext());
};
const hashSetScenario = () => {
return new JavaHashSetMarshaller().marshall(input, new MarshallingContext());
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const output = outputFunc();
expect(output).toBeNull();
});
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const arrayListScenario = () => {
return new JavaArrayListMarshaller().marshall(input, new MarshallingContext());
};
const hashSetScenario = () => {
return new JavaHashSetMarshaller().marshall(input, new MarshallingContext());
};
[arrayListScenario, hashSetScenario].forEach(outputFunc => {
const output = outputFunc();
expect(output).toBeNull();
});
});
});
describe("unmarshall", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
test("with empty collection, should unmarshall to empty collection", () => {
const arrayInput = {
input: new JavaArrayList([]),
marshaller: new JavaArrayListMarshaller(),
expected: []
};
const setInput = {
input: new JavaHashSet(new Set([])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with Array collection, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([["foo"]]),
marshaller: new JavaArrayListMarshaller(),
expected: [["foo"]]
};
const setInput = {
input: new JavaHashSet(new Set([["foo"]])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([["foo"]])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaArrayList collection, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaArrayList(["foo"])]),
marshaller: new JavaArrayListMarshaller(),
expected: [["foo"]]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaArrayList(["foo"])])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([["foo"]])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with Set input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new Set(["foo"])]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Set(["foo"])]
};
const setInput = {
input: new JavaHashSet(new Set([new Set(["foo"])])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Set(["foo"])])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with HashSet input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaHashSet(new Set(["foo"]))]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Set(["foo"])]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaHashSet(new Set(["foo"]))])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Set(["foo"])])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with Map input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new Map([["foo", "bar"]])]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Map([["foo", "bar"]])]
};
const setInput = {
input: new JavaHashSet(new Set([new Map([["foo", "bar"]])])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Map([["foo", "bar"]])])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaHashMap input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaHashMap(new Map([["foo", "bar"]]))]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Map([["foo", "bar"]])]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaHashMap(new Map([["foo", "bar"]]))])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Map([["foo", "bar"]])])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with Date input, should unmarshall correctly", () => {
const baseDate = new Date();
const arrayInput = {
input: new JavaArrayList([new Date(baseDate)]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Date(baseDate)]
};
const setInput = {
input: new JavaHashSet(new Set([new Date(baseDate)])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Date(baseDate)])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaDate input, should unmarshall correctly", () => {
const baseDate = new Date();
const arrayInput = {
input: new JavaArrayList([new JavaDate(new Date(baseDate))]),
marshaller: new JavaArrayListMarshaller(),
expected: [new Date(baseDate)]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaDate(new Date(baseDate))])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new Date(baseDate)])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with Boolean input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([false]),
marshaller: new JavaArrayListMarshaller(),
expected: [false]
};
const setInput = {
input: new JavaHashSet(new Set([false])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([false])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaBoolean input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaBoolean(false)]),
marshaller: new JavaArrayListMarshaller(),
expected: [false]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaBoolean(false)])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([false])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with String input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList(["foo"]),
marshaller: new JavaArrayListMarshaller(),
expected: ["foo"]
};
const setInput = {
input: new JavaHashSet(new Set(["foo"])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set(["foo"])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaString input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaString("foo")]),
marshaller: new JavaArrayListMarshaller(),
expected: ["foo"]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaString("foo")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set(["foo"])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaOptional input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaOptional("foo")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaOptional("foo")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaOptional("foo")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaOptional("foo")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaBigDecimal input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaBigDecimal("1.1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaBigDecimal("1.1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaBigDecimal("1.1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaBigDecimal("1.1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaBigInteger should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaBigInteger("1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaBigInteger("1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaBigInteger("1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaBigInteger("1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaLong input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaLong("1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaLong("1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaLong("1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaLong("1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaByte input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaByte("1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaByte("1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaByte("1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaByte("1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaDouble input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaDouble("1.1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaDouble("1.1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaDouble("1.1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaDouble("1.1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaFloat input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaFloat("1.1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaFloat("1.1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaFloat("1.1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaFloat("1.1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaInteger input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaInteger("1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaInteger("1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaInteger("1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaInteger("1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with JavaShort input, should unmarshall correctly", () => {
const arrayInput = {
input: new JavaArrayList([new JavaShort("1")]),
marshaller: new JavaArrayListMarshaller(),
expected: [new JavaShort("1")]
};
const setInput = {
input: new JavaHashSet(new Set([new JavaShort("1")])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new JavaShort("1")])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual(scenario.expected);
});
});
test("with custom object optional, should unmarshall correctly", () => {
const oracle = new Map([["com.portable.my", () => new MyPortable({} as any)]]);
const arrayInput = {
input: new JavaArrayList([new MyPortable({ foo: "bar", bar: "foo" })]),
marshaller: new JavaArrayListMarshaller(),
expected: [new MyPortable({ foo: "bar", bar: "foo" })]
};
const setInput = {
input: new JavaHashSet(new Set([new MyPortable({ foo: "bar", bar: "foo" })])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set([new MyPortable({ foo: "bar", bar: "foo" })])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(oracle));
expect(output).toEqual(scenario.expected);
});
});
test("with root null object, should unmarshall to undefined", () => {
[new JavaArrayListMarshaller(), new JavaHashSetMarshaller()].forEach(marshaller => {
const output = marshaller.unmarshall(null as any, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
});
test("with root undefined object, should unmarshall to undefined", () => {
[new JavaArrayListMarshaller(), new JavaHashSetMarshaller()].forEach(marshaller => {
const output = marshaller.unmarshall(undefined as any, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
});
test("with undefined value inside ErraiObject, should throw error", () => {
const arrayInput = {
input: new ValueBasedErraiObject(JavaType.ARRAY_LIST, undefined).asErraiObject(),
marshaller: new JavaArrayListMarshaller()
};
const setInput = {
input: new ValueBasedErraiObject(JavaType.HASH_SET, undefined).asErraiObject(),
marshaller: new JavaHashSetMarshaller()
};
[arrayInput, setInput].forEach(scenario => {
expect(() => scenario.marshaller.unmarshall(scenario.input, new UnmarshallingContext(new Map()))).toThrowError();
});
});
test("with null value inside ErraiObject, should throw error", () => {
const arrayInput = {
input: new ValueBasedErraiObject(JavaType.ARRAY_LIST, null).asErraiObject(),
marshaller: new JavaArrayListMarshaller()
};
const setInput = {
input: new ValueBasedErraiObject(JavaType.HASH_SET, null).asErraiObject(),
marshaller: new JavaHashSetMarshaller()
};
[arrayInput, setInput].forEach(scenario => {
expect(() => scenario.marshaller.unmarshall(scenario.input, new UnmarshallingContext(new Map()))).toThrowError();
});
});
test("with non array value inside ErraiObject, should throw error", () => {
const arrayInput = {
input: new ValueBasedErraiObject(JavaType.ARRAY_LIST, false).asErraiObject(),
marshaller: new JavaArrayListMarshaller()
};
const setInput = {
input: new ValueBasedErraiObject(JavaType.HASH_SET, false).asErraiObject(),
marshaller: new JavaHashSetMarshaller()
};
[arrayInput, setInput].forEach(scenario => {
expect(() => scenario.marshaller.unmarshall(scenario.input, new UnmarshallingContext(new Map()))).toThrowError();
});
});
test("with custom pojo containing repeated elements, should reuse cached objects and don't recreate data", () => {
const oracle = new Map([["com.app.my.Node", () => new Node({} as any)]]);
const repeatedValue = new Node({ data: "foo1" });
const portableArray = [repeatedValue, new Node({ data: "foo2", right: repeatedValue })];
const arrayInput = {
input: new JavaArrayList(portableArray),
marshaller: new JavaArrayListMarshaller(),
expected: portableArray
};
const setInput = {
input: new JavaHashSet(new Set(portableArray)),
marshaller: new JavaHashSetMarshaller(),
expected: new Set(portableArray)
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const output = scenario.marshaller.unmarshall(input, new UnmarshallingContext(oracle));
// compares value equality
expect(output).toEqual(scenario.expected);
// check if the repeated object was reused from cache
const asArray = Array.from(scenario.expected);
const repeatedNode = asArray[0];
const uniqueNode = asArray[1];
expect(repeatedNode).toBe(uniqueNode.right!);
});
});
test("with repeated collection unmarshalling, should reuse cached collection and don't recreate it", () => {
const arrayInput = {
input: new JavaArrayList(["list"]),
marshaller: new JavaArrayListMarshaller(),
expected: ["list"]
};
const setInput = {
input: new JavaHashSet(new Set(["set"])),
marshaller: new JavaHashSetMarshaller(),
expected: new Set(["set"])
};
[arrayInput, setInput].forEach(scenario => {
const input = (scenario.marshaller as any).marshall(scenario.input as any, new MarshallingContext());
const context = new UnmarshallingContext(new Map());
const output = scenario.marshaller.unmarshall(input, context);
const repeatedOutput = scenario.marshaller.unmarshall(input, context);
expect(output).toEqual(scenario.expected);
expect(output).toBe(repeatedOutput!);
});
});
});
class MyPortable implements Portable {
private readonly _fqcn = "com.portable.my";
public readonly foo: string;
public readonly bar: string;
constructor(self: { foo: string; bar: string }) {
Object.assign(this, self);
}
}
class Node implements Portable {
private readonly _fqcn = "com.app.my.Node";
public readonly data: any;
public readonly left?: Node;
public readonly right?: Node;
constructor(self: { data: any; left?: Node; right?: Node }) {
Object.assign(this, self);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaDateMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaDate } from "../../../java-wrappers";
import { JavaDateMarshaller } from "../JavaDateMarshaller";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
import { UnmarshallingContext } from "../../UnmarshallingContext";
describe("marshall", () => {
test("with regular date, should should serialize it normally", () => {
const date = new Date();
const input = new JavaDate(date);
const output = new JavaDateMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(new ValueBasedErraiObject(JavaType.DATE, `${date.getTime()}`).asErraiObject());
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaDateMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaDateMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with ErraiObject regular input, should return the same Date instance", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = new Date();
const expectedDate = new Date(input.getTime());
const marshalledInput = marshaller.notNullMarshall(new JavaDate(input), new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(expectedDate);
});
test("with non numeric string value, should throw error", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new ValueBasedErraiObject(JavaType.DATE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with non string value, should throw error", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = true as any;
const marshalledInput = new ValueBasedErraiObject(JavaType.DATE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with negative timestamp string value, should throw error", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "-1";
const marshalledInput = new ValueBasedErraiObject(JavaType.DATE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new ValueBasedErraiObject(JavaType.DATE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaDateMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new ValueBasedErraiObject(JavaType.DATE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaDoubleMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaDouble } from "../../../java-wrappers";
import { JavaDoubleMarshaller } from "../JavaDoubleMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
test("with regular double, should return the same value", () => {
const input = new JavaDouble("2.1");
const output = new JavaDoubleMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(2.1);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaDoubleMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaDoubleMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with number input, should return a JavaDouble instance", () => {
const marshaller = new JavaDoubleMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.1;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toEqual(new JavaDouble("1.1"));
});
test("with ErraiObject regular input, should return a JavaDouble instance", () => {
const marshaller = new JavaDoubleMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.1;
const marshalledInput = new NumValBasedErraiObject(JavaType.DOUBLE, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(new JavaDouble("1.1"));
});
test("with non double value, should throw error", () => {
const marshaller = new JavaDoubleMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.DOUBLE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaDoubleMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.DOUBLE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaDoubleMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.DOUBLE, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaEnumMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaEnum } from "../../../java-wrappers";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaEnumMarshaller } from "../JavaEnumMarshaller";
import { EnumStringValueBasedErraiObject } from "../../model/EnumStringValueBasedErraiObject";
describe("marshall", () => {
test("with regular enum, should return the same value", () => {
const input = FooEnum.BAR;
const output = new JavaEnumMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(
new EnumStringValueBasedErraiObject(FooEnum.__fqcn(), FooEnum.BAR.name).asErraiObject()
);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaEnumMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaEnumMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with enum input, should return an enum instance", () => {
const marshaller = new JavaEnumMarshaller();
const context = new UnmarshallingContext(
new Map([
[
`${FooEnum.__fqcn()}`,
((name: string) => {
switch (name) {
case "FOO":
return FooEnum.FOO;
case "BAR":
return FooEnum.BAR;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
])
);
const input = new EnumStringValueBasedErraiObject(FooEnum.__fqcn(), FooEnum.FOO.name).asErraiObject();
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toStrictEqual(FooEnum.FOO);
});
test("with invalid enum value, should throw error", () => {
const marshaller = new JavaEnumMarshaller();
const context = new UnmarshallingContext(
new Map([
[
`${FooEnum.__fqcn()}`,
((name: string) => {
switch (name) {
case "FOO":
return FooEnum.FOO;
case "BAR":
return FooEnum.BAR;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
])
);
const input = "abc" as any;
const marshalledInput = new EnumStringValueBasedErraiObject(FooEnum.__fqcn(), input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaEnumMarshaller();
const context = new UnmarshallingContext(
new Map([
[
`${FooEnum.__fqcn()}`,
((name: string) => {
switch (name) {
case "FOO":
return FooEnum.FOO;
case "BAR":
return FooEnum.BAR;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
])
);
const input = null as any;
const marshalledInput = new EnumStringValueBasedErraiObject(FooEnum.__fqcn(), input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaEnumMarshaller();
const context = new UnmarshallingContext(
new Map([
[
`${FooEnum.__fqcn()}`,
((name: string) => {
switch (name) {
case "FOO":
return FooEnum.FOO;
case "BAR":
return FooEnum.BAR;
default:
throw new Error(`Unknown value ${name} for enum AddressType!`);
}
}) as any
]
])
);
const input = undefined as any;
const marshalledInput = new EnumStringValueBasedErraiObject(FooEnum.__fqcn(), input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
class FooEnum extends JavaEnum {
public static readonly FOO: FooEnum = new FooEnum("FOO");
public static readonly BAR: FooEnum = new FooEnum("BAR");
protected readonly _fqcn: string = FooEnum.__fqcn();
public static __fqcn(): string {
return "com.app.my.AddressType";
}
public static values() {
return [FooEnum.FOO, FooEnum.BAR];
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaFloatMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaFloat } from "../../../java-wrappers";
import { JavaFloatMarshaller } from "../JavaFloatMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
test("with regular float, should return the same value", () => {
const input = new JavaFloat("2.1");
const output = new JavaFloatMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(2.1);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaFloatMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaFloatMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with number input, should return a JavaFloat instance", () => {
const marshaller = new JavaFloatMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.1;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toEqual(new JavaFloat("1.1"));
});
test("with ErraiObject regular input, should return a JavaFloat instance", () => {
const marshaller = new JavaFloatMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.1;
const marshalledInput = new NumValBasedErraiObject(JavaType.FLOAT, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(new JavaFloat("1.1"));
});
test("with non float value, should throw error", () => {
const marshaller = new JavaFloatMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.FLOAT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaFloatMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.FLOAT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaFloatMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.FLOAT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaHashMapMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallerProvider } from "../../MarshallerProvider";
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../../java-wrappers";
import { JavaHashMapMarshaller } from "../JavaHashMapMarshaller";
import { MarshallingContext } from "../../MarshallingContext";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { Portable } from "../../../marshalling/Portable";
import { DefaultMarshaller } from "../DefaultMarshaller";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { NumberUtils } from "../../../util/NumberUtils";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
const encodedType = ErraiObjectConstants.ENCODED_TYPE;
const objectId = ErraiObjectConstants.OBJECT_ID;
const value = ErraiObjectConstants.VALUE;
const json = ErraiObjectConstants.JSON;
beforeEach(() => {
MarshallerProvider.initialize();
});
test("with empty map, should serialize normally", () => {
const input = new JavaHashMap(new Map());
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {}
});
});
test("with string key and value, should serialize normally", () => {
const input = new JavaHashMap(new Map([["foo1", "bar1"], ["foo2", "bar2"]]));
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
foo1: "bar1",
foo2: "bar2"
}
});
});
test("with JavaNumber key and value, should wrap key and value into an errai object", () => {
const input = new JavaHashMap(
new Map([[new JavaInteger("11"), new JavaInteger("12")], [new JavaInteger("21"), new JavaInteger("22")]])
);
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
const expectedKey1 = `${json + JSON.stringify(new NumValBasedErraiObject(JavaType.INTEGER, 11).asErraiObject())}`;
const expectedKey2 = `${json + JSON.stringify(new NumValBasedErraiObject(JavaType.INTEGER, 21).asErraiObject())}`;
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[expectedKey1]: new NumValBasedErraiObject(JavaType.INTEGER, 12).asErraiObject(),
[expectedKey2]: new NumValBasedErraiObject(JavaType.INTEGER, 22).asErraiObject()
}
});
});
test("with JavaBoolean key and value, should wrap key and value into an errai object", () => {
const input = new JavaHashMap(
new Map([[new JavaBoolean(true), new JavaBoolean(false)], [new JavaBoolean(false), new JavaBoolean(true)]])
);
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
const expectedKey1 = `${json + JSON.stringify(new NumValBasedErraiObject(JavaType.BOOLEAN, true).asErraiObject())}`;
const expectedKey2 = `${json +
JSON.stringify(new NumValBasedErraiObject(JavaType.BOOLEAN, false).asErraiObject())}`;
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[expectedKey1]: new NumValBasedErraiObject(JavaType.BOOLEAN, false).asErraiObject(),
[expectedKey2]: new NumValBasedErraiObject(JavaType.BOOLEAN, true).asErraiObject()
}
});
});
test("with JavaBigNumber key and value, should wrap key and value into an errai object", () => {
const input = new JavaHashMap(
new Map([
[new JavaBigInteger("11"), new JavaBigInteger("12")],
[new JavaBigInteger("21"), new JavaBigInteger("22")]
])
);
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext())!;
// need to assert the keys individually because since it's a string, can't use the regex matcher in the object id :/
const mapKeys = Object.keys(output[value]);
expect(mapKeys.length).toBe(2);
const key1Str = mapKeys[0];
const key2Str = mapKeys[1];
mapKeys.forEach(k => {
// complex objects as map key uses a prefix to indicate that a json must be parsed in the map key
expect(k.startsWith(json)).toBeTruthy();
});
const key1Obj = JSON.parse(key1Str.replace(json, ""));
const key2Obj = JSON.parse(key2Str.replace(json, ""));
expect(key1Obj).toStrictEqual({
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "11"
});
expect(key2Obj).toStrictEqual({
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "21"
});
// assert map values
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[key1Str]: {
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "12"
},
[key2Str]: {
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "22"
}
}
});
});
test("with custom object key and value, should wrap key and value into an errai object", () => {
const input = new JavaHashMap(
new Map([
[new DummyPojo({ foo: "bar11" }), new DummyPojo({ foo: "bar12" })],
[new DummyPojo({ foo: "bar21" }), new DummyPojo({ foo: "bar22" })]
])
);
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext())!;
// need to assert the keys individually because since it's a string, can't use the regex matcher in the object id :/
const mapKeys = Object.keys(output[value]);
expect(mapKeys.length).toBe(2);
const key1Str = mapKeys[0];
const key2Str = mapKeys[1];
mapKeys.forEach(k => {
// complex objects as map key uses a prefix to indicate that a json must be parsed in the map key
expect(k.startsWith(json)).toBeTruthy();
});
const key1Obj = JSON.parse(key1Str.replace(json, ""));
const key2Obj = JSON.parse(key2Str.replace(json, ""));
expect(key1Obj).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "bar11"
});
expect(key2Obj).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "bar21"
});
// assert map values
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[key1Str]: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "bar12"
},
[key2Str]: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "bar22"
}
}
});
});
test("with undefined key and value, should set key as null reference and value as null", () => {
const input = new JavaHashMap(new Map([[undefined, undefined]]));
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[ErraiObjectConstants.NULL]: null
}
});
});
test("with custom pojo containing cached key, should reuse it and don't repeat data", () => {
const repeatedPojo = new DummyPojo({ foo: "repeatedKey" });
const input = new ComplexPojo({
dummy: repeatedPojo,
map: new Map([[repeatedPojo, "value1"], [new DummyPojo({ foo: "uniqueKey" }), "value2"]])
});
const context = new MarshallingContext();
const output = new DefaultMarshaller().marshall(input, context)!;
// ===== assertions
// 1) Assert map content
const mapOutput = (output as any).map;
const mapKeys = Object.keys(mapOutput[value]);
expect(mapKeys.length).toBe(2);
const key1Str = mapKeys[0];
const key2Str = mapKeys[1];
mapKeys.forEach(k => {
// complex objects as map key uses a prefix to indicate that a json must be parsed in the map key
expect(k.startsWith(json)).toBeTruthy();
});
const key1Obj = JSON.parse(key1Str.replace(json, ""));
const key2Obj = JSON.parse(key2Str.replace(json, ""));
// assert keys contents
const key1ObjectId = key1Obj[objectId]; // this is the cached object's id
expect(key1ObjectId).toMatch(NumberUtils.nonNegativeIntegerRegex);
expect(key1Obj).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: key1ObjectId // without object's content
});
expect(key2Obj).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "uniqueKey"
});
// assert map values contents
expect(mapOutput).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
[key1Str]: "value1",
[key2Str]: "value2"
}
});
// 2) Assert full object content
expect(output).toStrictEqual({
[encodedType]: "com.app.my.ComplexPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
dummy: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: key1ObjectId, // same object id than the one used as map key
foo: "repeatedKey"
},
map: mapOutput // already asserted
});
// do not cache repeated object's data
expect(context.getCached(repeatedPojo)).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: key1ObjectId
});
});
test("with map containing repeated value, should reuse it and don't repeat data", () => {
const repeatedValue = new DummyPojo({ foo: "repeatedValue" });
const uniqueValue = new DummyPojo({ foo: "uniqueValue" });
const input = new JavaHashMap(new Map([["key1", repeatedValue], ["key2", repeatedValue], ["key3", uniqueValue]]));
const context = new MarshallingContext();
const output = new JavaHashMapMarshaller().marshall(input, context);
expect(output).toStrictEqual({
[encodedType]: JavaType.HASH_MAP,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: {
key1: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "repeatedValue"
},
key2: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex)
// missing data
},
key3: {
[encodedType]: "com.app.my.DummyPojo",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "uniqueValue"
}
}
});
// same object id
const repeatedObjIdFirstAppearance = (output as any)[value].key1[objectId];
const repeatedObjIdSecondAppearance = (output as any)[value].key2[objectId];
expect(repeatedObjIdFirstAppearance).toEqual(repeatedObjIdSecondAppearance);
// do not cache repeated object's data
expect(context.getCached(repeatedValue)).toStrictEqual({
[encodedType]: "com.app.my.DummyPojo",
[objectId]: repeatedObjIdFirstAppearance
});
});
test("with root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("with root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaHashMapMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
test("with empty map, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map());
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map());
});
test("with string key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const stringInput = new JavaHashMap(new Map([["foo1", "bar1"]]));
const javaStringInput = new JavaHashMap(new Map([[new JavaString("foo1"), new JavaString("bar1")]]));
[stringInput, javaStringInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([["foo1", "bar1"]]));
});
});
test("with Array key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const arrayInput = new JavaHashMap(new Map([[["foo1"], ["bar1"]]]));
const arrayListInput = new JavaHashMap(new Map([[new JavaArrayList(["foo1"]), new JavaArrayList(["bar1"])]]));
[arrayInput, arrayListInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[["foo1"], ["bar1"]]]));
});
});
test("with Set key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const setInput = new JavaHashMap(new Map([[new Set(["foo1"]), new Set(["bar1"])]]));
const hashSetInput = new JavaHashMap(
new Map([[new JavaHashSet(new Set(["foo1"])), new JavaHashSet(new Set(["bar1"]))]])
);
[setInput, hashSetInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new Set(["foo1"]), new Set(["bar1"])]]));
});
});
test("with Map key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const mapInput = new JavaHashMap(new Map([[new Map([["kfoo1", "kbar1"]]), new Map([["vfoo1", "vbar1"]])]]));
const hashMapInput = new JavaHashMap(
new Map([[new JavaHashMap(new Map([["kfoo1", "kbar1"]])), new JavaHashMap(new Map([["vfoo1", "vbar1"]]))]])
);
[mapInput, hashMapInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new Map([["kfoo1", "kbar1"]]), new Map([["vfoo1", "vbar1"]])]]));
});
});
test("with Date key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const baseDateKey = new Date();
const baseDateValue = new Date();
const dateInput = new JavaHashMap(new Map([[baseDateKey, baseDateValue]]));
const javaDateInput = new JavaHashMap(new Map([[new JavaDate(baseDateKey), new JavaDate(baseDateValue)]]));
[dateInput, javaDateInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[baseDateKey, baseDateValue]]));
});
});
test("with Boolean key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const booleanInput = new JavaHashMap(new Map([[false, true]]));
const javaBooleanInput = new JavaHashMap(new Map([[new JavaBoolean(false), new JavaBoolean(true)]]));
[booleanInput, javaBooleanInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[false, true]]));
});
});
test("with String key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const stringInput = new JavaHashMap(new Map([["foo", "bar"]]));
const javaStringInput = new JavaHashMap(new Map([[new JavaString("foo"), new JavaString("bar")]]));
[stringInput, javaStringInput].forEach(input => {
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([["foo", "bar"]]));
});
});
test("with JavaOptional key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaOptional("foo"), new JavaOptional("bar")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaOptional("foo"), new JavaOptional("bar")]]));
});
test("with JavaBigDecimal key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaBigDecimal("1.1"), new JavaBigDecimal("1.1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaBigDecimal("1.1"), new JavaBigDecimal("1.1")]]));
});
test("with JavaBigInteger key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaBigInteger("1"), new JavaBigInteger("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaBigInteger("1"), new JavaBigInteger("1")]]));
});
test("with JavaLong key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaLong("1"), new JavaLong("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaLong("1"), new JavaLong("1")]]));
});
test("with JavaByte key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaByte("1"), new JavaByte("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaByte("1"), new JavaByte("1")]]));
});
test("with JavaDouble key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaDouble("1.1"), new JavaDouble("1.1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaDouble("1.1"), new JavaDouble("1.1")]]));
});
test("with JavaFloat key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaFloat("1.1"), new JavaFloat("1.1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaFloat("1.1"), new JavaFloat("1.1")]]));
});
test("with JavaInteger key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaInteger("1"), new JavaInteger("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaInteger("1"), new JavaInteger("1")]]));
});
test("with JavaShort key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaShort("1"), new JavaShort("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaShort("1"), new JavaShort("1")]]));
});
test("with JavaShort key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[new JavaShort("1"), new JavaShort("1")]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[new JavaShort("1"), new JavaShort("1")]]));
});
test("with custom object key and value, should unmarshall correctly", () => {
const oracle = new Map([["com.app.my.DummyPojo", () => new DummyPojo({} as any)]]);
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(
new Map([
[new DummyPojo({ foo: "bar11" }), new DummyPojo({ foo: "bar12" })],
[new DummyPojo({ foo: "bar21" }), new DummyPojo({ foo: "bar22" })]
])
);
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(oracle));
expect(output).toEqual(
new Map([
[new DummyPojo({ foo: "bar11" }), new DummyPojo({ foo: "bar12" })],
[new DummyPojo({ foo: "bar21" }), new DummyPojo({ foo: "bar22" })]
])
);
});
test("with undefined key and value, should unmarshall correctly", () => {
const marshaller = new JavaHashMapMarshaller();
const input = new JavaHashMap(new Map([[undefined, undefined]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(new Map([[undefined, undefined]]));
});
test("with custom pojo containing cached key, should reuse cached objects and don't recreate data", () => {
const marshaller = new DefaultMarshaller();
const oracle: Map Portable> = new Map([
["com.app.my.DummyPojo", () => new DummyPojo({} as any) as any],
["com.app.my.ComplexPojo", () => new ComplexPojo({} as any) as any]
]);
const repeatedPojo = new DummyPojo({ foo: "repeatedKey" });
const input = new ComplexPojo({
dummy: repeatedPojo,
map: new Map([[repeatedPojo, "value1"], [new DummyPojo({ foo: "uniqueKey" }), "value2"]])
});
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle))! as ComplexPojo;
// ===== assertions
// successfully unmarshalled
expect(output).toEqual(input);
// same object for the cached one
const repeatedPojoFromKey = output.map.keys().next().value;
expect(output.dummy).toBe(repeatedPojoFromKey);
});
test("with map containing repeated value, should reuse cached objects and don't recreate data", () => {
const marshaller = new JavaHashMapMarshaller();
const oracle: Map Portable> = new Map([
["com.app.my.DummyPojo", () => new DummyPojo({} as any)]
]);
const repeatedPojo = new DummyPojo({ foo: "repeatedKey" });
const input = new JavaHashMap(new Map([["k1", repeatedPojo], ["k2", repeatedPojo]]));
const marshalledInput = marshaller.marshall(input, new MarshallingContext())!;
const output = marshaller.unmarshall(marshalledInput, new UnmarshallingContext(oracle))!;
// ===== assertions
// successfully unmarshalled
expect(output).toEqual(new Map([["k1", repeatedPojo], ["k2", repeatedPojo]]));
// same objects for the values
expect(output.get("k1")!).toBe(output.get("k2")!);
});
test("with null inside ErraiObject's value, should throw error", () => {
const context = new UnmarshallingContext(new Map());
const marshaller = new JavaHashMapMarshaller();
const marshalledInput = new ValueBasedErraiObject(JavaType.HASH_MAP, null as any).asErraiObject();
expect(() => marshaller.unmarshall(marshalledInput!, context)).toThrowError();
});
});
class DummyPojo implements Portable {
private readonly _fqcn = "com.app.my.DummyPojo";
public readonly foo: string;
constructor(self: { foo: string }) {
Object.assign(this, self);
}
}
class ComplexPojo implements Portable {
private readonly _fqcn = "com.app.my.ComplexPojo";
public dummy: DummyPojo;
public map: Map;
constructor(self: { dummy: DummyPojo; map: Map }) {
Object.assign(this, self);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaIntegerMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaInteger } from "../../../java-wrappers";
import { JavaIntegerMarshaller } from "../JavaIntegerMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
test("with regular integer, should return the same value", () => {
const input = new JavaInteger("2");
const output = new JavaIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(2);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaIntegerMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
describe("number input", () => {
test("with integer, should return a JavaInteger instance", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toEqual(new JavaInteger("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
});
describe("ErraiObject input", () => {
test("with integer, should return a JavaInteger instance", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(new JavaInteger("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaLongMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaLong } from "../../../java-wrappers";
import { JavaLongMarshaller } from "../JavaLongMarshaller";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaType } from "../../../java-wrappers/JavaType";
import { JavaIntegerMarshaller } from "../JavaIntegerMarshaller";
describe("marshall", () => {
test("with regular long, should should serialize it normally", () => {
const input = new JavaLong("2");
const output = new JavaLongMarshaller().marshall(input, new MarshallingContext());
const expected = new NumValBasedErraiObject(JavaType.LONG, "2").asErraiObject();
expect(output).toStrictEqual(expected);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaLongMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaLongMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with regular input, should return a JavaLong instance", () => {
const marshaller = new JavaLongMarshaller();
const context = new UnmarshallingContext(new Map());
const input = new JavaLong("125");
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output.get()).toEqual(input.get());
});
test("with float string value, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "1.2";
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with non numeric string value, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null value, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined value, should throw error", () => {
const marshaller = new JavaIntegerMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.INTEGER, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaOptionalMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../../java-wrappers";
import { ErraiObjectConstants } from "../../model/ErraiObjectConstants";
import { MarshallerProvider } from "../../MarshallerProvider";
import { Portable } from "../../Portable";
import { JavaOptionalMarshaller } from "../JavaOptionalMarshaller";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { ValueBasedErraiObject } from "../../model/ValueBasedErraiObject";
import { NumberUtils } from "../../../util/NumberUtils";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
const encodedType = ErraiObjectConstants.ENCODED_TYPE;
const objectId = ErraiObjectConstants.OBJECT_ID;
const value = ErraiObjectConstants.VALUE;
let context: MarshallingContext;
beforeEach(() => {
MarshallerProvider.initialize();
context = new MarshallingContext();
});
test("with empty optional, should serialize normally", () => {
const input = new JavaOptional(undefined);
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toStrictEqual(new ValueBasedErraiObject(JavaType.OPTIONAL, null).asErraiObject());
});
test("with JavaNumber optional, should wrap element into an errai object", () => {
const input = new JavaOptional(new JavaInteger("1"));
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toStrictEqual(
new ValueBasedErraiObject(
JavaType.OPTIONAL,
new NumValBasedErraiObject(JavaType.INTEGER, 1).asErraiObject()
).asErraiObject()
);
});
test("with JavaBoolean optional, should wrap element into an errai object", () => {
const input = new JavaOptional(new JavaBoolean(false));
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toStrictEqual(
new ValueBasedErraiObject(
JavaType.OPTIONAL,
new NumValBasedErraiObject(JavaType.BOOLEAN, false).asErraiObject()
).asErraiObject()
);
});
test("with JavaBigNumber optional, should serialize element normally", () => {
const input = new JavaOptional(new JavaBigInteger("1"));
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toStrictEqual({
[encodedType]: JavaType.OPTIONAL,
[objectId]: "-1",
[value]: {
[encodedType]: JavaType.BIG_INTEGER,
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
[value]: "1"
}
});
});
test("with custom object optional, should serialize element normally", () => {
const input = new JavaOptional(new MyPortable({ foo: "foo1", bar: "bar1" }));
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toStrictEqual({
[encodedType]: JavaType.OPTIONAL,
[objectId]: "-1",
[value]: {
[encodedType]: "com.portable.my",
[objectId]: expect.stringMatching(NumberUtils.nonNegativeIntegerRegex),
foo: "foo1",
bar: "bar1"
}
});
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaOptionalMarshaller().marshall(input, context);
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
beforeEach(() => {
MarshallerProvider.initialize();
});
test("with empty optional, should return an empty optional", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(undefined);
const marshalledInput = marshaller.marshall(input, new MarshallingContext());
const output = marshaller.unmarshall(marshalledInput!, new UnmarshallingContext(new Map()));
expect(output).toEqual(input);
});
test("with Array input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const arrayInput = new JavaOptional(["str1", "str2"]);
const arrayListInput = new JavaOptional>(new JavaArrayList(["str1", "str2"]));
[arrayInput, arrayListInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(["str1", "str2"]));
});
});
test("with Set input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const setInput = new JavaOptional>(new Set(["str1", "str2"]));
const hashSetInput = new JavaOptional>(new JavaHashSet(new Set(["str1", "str2"])));
[setInput, hashSetInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new Set(["str1", "str2"])));
});
});
test("with Map input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const mapInput = new JavaOptional>(new Map([["str1", "str2"]]));
const hashMapInput = new JavaOptional>(new JavaHashMap(new Map([["str1", "str2"]])));
[mapInput, hashMapInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new Map([["str1", "str2"]])));
});
});
test("with Date input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const baseDate = new Date();
const dateInput = new JavaOptional(new Date(baseDate));
const javaDateInput = new JavaOptional(new JavaDate(baseDate));
[dateInput, javaDateInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new Date(baseDate)));
});
});
test("with Boolean input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const booleanInput = new JavaOptional(false);
const javaBooleanInput = new JavaOptional(new JavaBoolean(false));
[booleanInput, javaBooleanInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(false));
});
});
test("with String input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const stringInput = new JavaOptional("foo");
const javaStringInput = new JavaOptional(new JavaString("foo"));
[stringInput, javaStringInput].forEach(input => {
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional("foo"));
});
});
test("with JavaOptional input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaOptional("foo"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaOptional("foo")));
});
test("with JavaBigDecimal input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaBigDecimal("1.1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaBigDecimal("1.1")));
});
test("with JavaBigInteger should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaBigInteger("1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaBigInteger("1")));
});
test("with JavaLong input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaLong("1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaLong("1")));
});
test("with JavaByte input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaByte("1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaByte("1")));
});
test("with JavaDouble input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaDouble("1.1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaDouble("1.1")));
});
test("with JavaFloat input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaFloat("1.1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaFloat("1.1")));
});
test("with JavaInteger input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaInteger("1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaInteger("1")));
});
test("with JavaShort input, should unmarshall correctly", () => {
const marshaller = new JavaOptionalMarshaller();
const input = new JavaOptional(new JavaShort("1"));
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual(new JavaOptional(new JavaShort("1")));
});
test("with custom object optional, should unmarshall correctly", () => {
const oracle = new Map([["com.portable.my", () => new MyPortable({} as any)]]);
const marshaller = new JavaOptionalMarshaller();
const pojoInput = new MyPortable({ foo: "foo1", bar: "bar1" });
const optionalInput = new JavaOptional(pojoInput);
const marshalledInput = marshaller.notNullMarshall(optionalInput, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(oracle));
expect(output).toEqual(new JavaOptional(pojoInput));
});
test("with root null object, should unmarshall to null", () => {
const input = null as any;
const output = new JavaOptionalMarshaller().unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
test("with root undefined object, should unmarshall to undefined", () => {
const input = undefined as any;
const output = new JavaOptionalMarshaller().unmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toBeUndefined();
});
});
class MyPortable implements Portable {
private readonly _fqcn = "com.portable.my";
public readonly foo: string;
public readonly bar: string;
constructor(self: { foo: string; bar: string }) {
Object.assign(this, self);
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaShortMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaShort } from "../../../java-wrappers";
import { JavaShortMarshaller } from "../JavaShortMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
import { JavaType } from "../../../java-wrappers/JavaType";
describe("marshall", () => {
test("with regular short, should return the same value", () => {
const input = new JavaShort("2");
const output = new JavaShortMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual(2);
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaShortMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaShortMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
describe("number input", () => {
test("with short, should return a JavaShort instance", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const output = marshaller.notNullUnmarshall(input, context);
expect(output).toEqual(new JavaShort("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
expect(() => marshaller.notNullUnmarshall(input, context)).toThrowError();
});
});
describe("ErraiObject input", () => {
test("with short, should return a JavaShort instance", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
const output = marshaller.notNullUnmarshall(marshalledInput, context);
expect(output).toEqual(new JavaShort("1"));
});
test("with float, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = 1.2;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with string, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = "abc" as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with null, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = null as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
test("with undefined, should throw error", () => {
const marshaller = new JavaShortMarshaller();
const context = new UnmarshallingContext(new Map());
const input = undefined as any;
const marshalledInput = new NumValBasedErraiObject(JavaType.SHORT, input).asErraiObject();
expect(() => marshaller.notNullUnmarshall(marshalledInput, context)).toThrowError();
});
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/__tests__/JavaStringMarshaller.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { MarshallingContext } from "../../MarshallingContext";
import { JavaString } from "../../../java-wrappers";
import { JavaStringMarshaller } from "../JavaStringMarshaller";
import { UnmarshallingContext } from "../../UnmarshallingContext";
describe("marshall", () => {
test("with regular string, should return the same value", () => {
const input = new JavaString("str");
const output = new JavaStringMarshaller().marshall(input, new MarshallingContext());
expect(output).toStrictEqual("str");
});
test("root null object, should serialize to null", () => {
const input = null as any;
const output = new JavaStringMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
test("root undefined object, should serialize to null", () => {
const input = undefined as any;
const output = new JavaStringMarshaller().marshall(input, new MarshallingContext());
expect(output).toBeNull();
});
});
describe("unmarshall", () => {
test("with string value, should return same string", () => {
const marshaller = new JavaStringMarshaller();
const input = new JavaString("foo");
const marshalledInput = marshaller.notNullMarshall(input, new MarshallingContext());
const output = marshaller.notNullUnmarshall(marshalledInput, new UnmarshallingContext(new Map()));
expect(output).toEqual("foo");
});
test("with JavaString value, should return inner string", () => {
const marshaller = new JavaStringMarshaller();
const input = new JavaString("foo");
const output = marshaller.notNullUnmarshall(input, new UnmarshallingContext(new Map()));
expect(output).toEqual("foo");
});
});
================================================
FILE: appformer-js/src/marshalling/marshallers/util/GenericsTypeMarshallingUtils.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NumberWrapper } from "../../../java-wrappers/NumberWrapper";
import { JavaBoolean } from "../../../java-wrappers";
import { Portable } from "../../../marshalling/Portable";
import { ErraiObject } from "../../model/ErraiObject";
import { MarshallingContext } from "../../MarshallingContext";
import { MarshallerProvider } from "../../MarshallerProvider";
import { JavaWrapperUtils } from "../../../java-wrappers/JavaWrapperUtils";
import { NumValBasedErraiObject } from "../../model/NumValBasedErraiObject";
export class GenericsTypeMarshallingUtils {
private static shouldWrapAsGenericsType(value: Portable) {
return value instanceof NumberWrapper || value instanceof JavaBoolean;
}
private static wrapGenericsTypeElement(value: Portable, marshalledValue: any): ErraiObject {
// This is mandatory in order to comply with errai-marshalling protocol.
// When marshalling numeric or boolean values, we use its raw value, without any ErraiObject envelope.
// But, when the value is a generic type, we always wrap it inside an ErraiObject
return new NumValBasedErraiObject((value as any)._fqcn, marshalledValue).asErraiObject();
}
public static marshallGenericsTypeElement(value: any, ctx: MarshallingContext): ErraiObject {
// apply automatic native types -> java types conversion
const enhancedInput = JavaWrapperUtils.wrapIfNeeded(value);
const marshaller = MarshallerProvider.getForObject(enhancedInput);
const marshalledValue = marshaller.marshall(enhancedInput, ctx);
if (this.shouldWrapAsGenericsType(enhancedInput)) {
return this.wrapGenericsTypeElement(enhancedInput, marshalledValue)!;
}
return marshalledValue;
}
}
================================================
FILE: appformer-js/src/marshalling/marshallers/util/__tests__/GenericsTypeMarshallingUtils.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import {
JavaArrayList,
JavaBigDecimal,
JavaBigInteger,
JavaBoolean,
JavaByte,
JavaDate,
JavaDouble,
JavaFloat,
JavaHashMap,
JavaHashSet,
JavaInteger,
JavaLong,
JavaOptional,
JavaShort,
JavaString
} from "../../../../java-wrappers";
import { GenericsTypeMarshallingUtils } from "../GenericsTypeMarshallingUtils";
import { MarshallingContext } from "../../../MarshallingContext";
import { JavaArrayListMarshaller, JavaHashSetMarshaller } from "../../JavaCollectionMarshaller";
import { ErraiObjectConstants } from "../../../model/ErraiObjectConstants";
import { MarshallerProvider } from "../../../MarshallerProvider";
import { JavaBigDecimalMarshaller } from "../../JavaBigDecimalMarshaller";
import { JavaBigIntegerMarshaller } from "../../JavaBigIntegerMarshaller";
import { JavaHashMapMarshaller } from "../../JavaHashMapMarshaller";
import { JavaLongMarshaller } from "../../JavaLongMarshaller";
import { JavaStringMarshaller } from "../../JavaStringMarshaller";
import { JavaDateMarshaller } from "../../JavaDateMarshaller";
import { DefaultMarshaller } from "../../DefaultMarshaller";
import { Portable } from "../../../Portable";
import { JavaOptionalMarshaller } from "../../JavaOptionalMarshaller";
import { NumValBasedErraiObject } from "../../../model/NumValBasedErraiObject";
import { JavaType } from "../../../../java-wrappers/JavaType";
describe("marshallGenericsTypeElement", () => {
const objectId = ErraiObjectConstants.OBJECT_ID;
beforeEach(() => {
MarshallerProvider.initialize();
});
test("with array input, should marshall with regular marshalling", () => {
const baseArray = ["str1", "str2"];
const arrayInput = {
input: baseArray,
inputAsJavaArrayList: new JavaArrayList(baseArray)
};
const javaArrayListInput = {
input: new JavaArrayList(baseArray),
inputAsJavaArrayList: new JavaArrayList(baseArray)
};
[arrayInput, javaArrayListInput].forEach(({ input, inputAsJavaArrayList }) => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaArrayListMarshaller().marshall(inputAsJavaArrayList, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
});
test("with Set input, should marshall with regular marshalling", () => {
const baseSet = new Set(["str1", "str2"]);
const setInput = {
input: baseSet,
inputAsJavaHashSet: new JavaHashSet(baseSet)
};
const javaHashSetInput = {
input: new JavaHashSet(baseSet),
inputAsJavaHashSet: new JavaHashSet(baseSet)
};
[setInput, javaHashSetInput].forEach(({ input, inputAsJavaHashSet }) => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaHashSetMarshaller().marshall(inputAsJavaHashSet, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
});
test("with JavaBigDecimal input, should marshall with regular marshalling", () => {
const input = new JavaBigDecimal("1.1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaBigDecimalMarshaller().marshall(input, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
test("with JavaBigInteger input, should marshall with regular marshalling", () => {
const input = new JavaBigInteger("1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaBigIntegerMarshaller().marshall(input, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
test("with map input, should marshall with regular marshalling", () => {
const baseMap = new Map([["foo1", "bar1"], ["foo2", "bar2"]]);
const mapInput = { input: baseMap, inputAsJavaHashMap: new JavaHashMap(baseMap) };
const javaHashMapInput = {
input: new JavaHashMap(baseMap),
inputAsJavaHashMap: new JavaHashMap(baseMap)
};
[mapInput, javaHashMapInput].forEach(({ input, inputAsJavaHashMap }) => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaHashMapMarshaller().marshall(inputAsJavaHashMap, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
});
test("with JavaLong input, should marshall with regular marshalling", () => {
const input = new JavaLong("1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaLongMarshaller().marshall(input, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
test("with string input, should marshall with regular marshalling", () => {
const stringInput = {
input: "str",
inputAsJavaString: new JavaString("str")
};
const javaStringInput = {
input: new JavaString("str"),
inputAsJavaString: new JavaString("str")
};
[stringInput, javaStringInput].forEach(({ input, inputAsJavaString }) => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaStringMarshaller().marshall(inputAsJavaString, new MarshallingContext())!;
expect(output).toStrictEqual(expected);
});
});
test("with date input, should marshall with regular marshalling", () => {
const baseDate = new Date();
const dateInput = {
input: baseDate,
inputAsJavaDate: new JavaDate(baseDate)
};
const javaDateInput = {
input: new JavaDate(baseDate),
inputAsJavaDate: new JavaDate(baseDate)
};
[dateInput, javaDateInput].forEach(({ input, inputAsJavaDate }) => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaDateMarshaller().marshall(inputAsJavaDate, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
});
test("with JavaOptional input, should marshall with regular marshalling", () => {
const input = new JavaOptional("str");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new JavaOptionalMarshaller().marshall(input, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
test("with custom portable input, should marshall with regular marshalling", () => {
const input = new Pojo("bar");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
const expected = new DefaultMarshaller().marshall(input, new MarshallingContext())!;
// don't care about the ids
delete output[objectId];
delete expected[objectId];
expect(output).toStrictEqual(expected);
});
test("with boolean input, should return input wrapped as an ErraiObject", () => {
const booleanInput = false;
const javaBooleanInput = new JavaBoolean(false);
[booleanInput, javaBooleanInput].forEach(input => {
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.BOOLEAN, false).asErraiObject());
});
});
test("with JavaByte input, should return input wrapped as an ErraiObject", () => {
const input = new JavaByte("1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.BYTE, 1).asErraiObject());
});
test("with JavaDouble input, should return input wrapped as an ErraiObject", () => {
const input = new JavaDouble("1.1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.DOUBLE, 1.1).asErraiObject());
});
test("with JavaFloat input, should return input wrapped as an ErraiObject", () => {
const input = new JavaFloat("1.1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.FLOAT, 1.1).asErraiObject());
});
test("with JavaInteger input, should return input wrapped as an ErraiObject", () => {
const input = new JavaInteger("1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.INTEGER, 1).asErraiObject());
});
test("with JavaShort input, should return input wrapped as an ErraiObject", () => {
const input = new JavaShort("1");
const output = GenericsTypeMarshallingUtils.marshallGenericsTypeElement(input, new MarshallingContext());
expect(output).toStrictEqual(new NumValBasedErraiObject(JavaType.SHORT, 1).asErraiObject());
});
class Pojo implements Portable {
private readonly _fqcn = "com.app.my.Pojo";
public foo: string;
constructor(foo: string) {
this.foo = foo;
}
}
});
================================================
FILE: appformer-js/src/marshalling/model/EnumStringValueBasedErraiObject.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObject } from "./ErraiObject";
import { ErraiObjectConstants } from "./ErraiObjectConstants";
export class EnumStringValueBasedErraiObject {
public readonly encodedType: string;
public readonly enumValueName: string;
constructor(encodedType: string, enumValueName: string) {
this.encodedType = encodedType;
this.enumValueName = enumValueName;
}
public asErraiObject(): ErraiObject {
return {
[ErraiObjectConstants.ENCODED_TYPE]: this.encodedType,
[ErraiObjectConstants.ENUM_STRING_VALUE]: this.enumValueName
};
}
public static from(obj: ErraiObject): EnumStringValueBasedErraiObject {
return new EnumStringValueBasedErraiObject(
obj[ErraiObjectConstants.ENCODED_TYPE],
obj[ErraiObjectConstants.ENUM_STRING_VALUE]!
);
}
}
================================================
FILE: appformer-js/src/marshalling/model/ErraiObject.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObjectConstants } from "./ErraiObjectConstants";
export interface ErraiObject {
[ErraiObjectConstants.ENCODED_TYPE]: string;
[ErraiObjectConstants.OBJECT_ID]?: string;
[ErraiObjectConstants.NUM_VAL]?: string | number | boolean;
[ErraiObjectConstants.VALUE]?: any;
[ErraiObjectConstants.ENUM_STRING_VALUE]?: string;
}
================================================
FILE: appformer-js/src/marshalling/model/ErraiObjectConstants.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export enum ErraiObjectConstants {
ENCODED_TYPE = "^EncodedType",
OBJECT_ID = "^ObjectID",
NUM_VAL = "^NumVal",
VALUE = "^Value",
JSON = "^${$JSON$}$::",
NULL = "^NullVal",
ENUM_STRING_VALUE = "^EnumStringValue"
}
================================================
FILE: appformer-js/src/marshalling/model/NumValBasedErraiObject.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObject } from "./ErraiObject";
import { ErraiObjectConstants } from "./ErraiObjectConstants";
export class NumValBasedErraiObject {
public readonly encodedType: string;
public readonly objId: string;
public readonly numVal: number | boolean | string;
constructor(encodedType: string, numVal: number | boolean | string, objectId: string = "-1") {
this.encodedType = encodedType;
this.numVal = numVal;
this.objId = objectId;
}
public asErraiObject(): ErraiObject {
return {
[ErraiObjectConstants.ENCODED_TYPE]: this.encodedType,
[ErraiObjectConstants.OBJECT_ID]: this.objId,
[ErraiObjectConstants.NUM_VAL]: this.numVal
};
}
public static from(obj: ErraiObject): NumValBasedErraiObject {
return new NumValBasedErraiObject(
obj[ErraiObjectConstants.ENCODED_TYPE],
obj[ErraiObjectConstants.NUM_VAL]!,
obj[ErraiObjectConstants.OBJECT_ID]
);
}
}
================================================
FILE: appformer-js/src/marshalling/model/ValueBasedErraiObject.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObject } from "./ErraiObject";
import { ErraiObjectConstants } from "./ErraiObjectConstants";
export class ValueBasedErraiObject {
public readonly encodedType: string;
public readonly objId: string;
public readonly value: any;
constructor(encodedType: string, value: any, objectId: string = "-1") {
this.encodedType = encodedType;
this.value = value;
this.objId = objectId;
}
public asErraiObject(): ErraiObject {
return {
[ErraiObjectConstants.ENCODED_TYPE]: this.encodedType,
[ErraiObjectConstants.OBJECT_ID]: this.objId,
[ErraiObjectConstants.VALUE]: this.value
};
}
public static from(obj: ErraiObject): ValueBasedErraiObject {
return new ValueBasedErraiObject(
obj[ErraiObjectConstants.ENCODED_TYPE],
obj[ErraiObjectConstants.VALUE],
obj[ErraiObjectConstants.OBJECT_ID]
);
}
}
================================================
FILE: appformer-js/src/marshalling/model/__tests__/EnumStringValueBasedErraiObject.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { ErraiObjectConstants } from "../ErraiObjectConstants";
import { EnumStringValueBasedErraiObject } from "../EnumStringValueBasedErraiObject";
describe("asErraiObject", () => {
test("with correct inputs, should return correct a well formed Errai Object", () => {
const input = new EnumStringValueBasedErraiObject("com.app.my", "foo");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.ENUM_STRING_VALUE]: "foo"
});
});
});
describe("from", () => {
test("with well formed errai object instance, should retrieve its data correctly", () => {
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.ENUM_STRING_VALUE]: "foo"
};
const output = EnumStringValueBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.enumValueName).toEqual("foo");
});
});
================================================
FILE: appformer-js/src/marshalling/model/__tests__/NumValBasedErraiObject.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NumValBasedErraiObject } from "../NumValBasedErraiObject";
import { ErraiObjectConstants } from "../ErraiObjectConstants";
import { isBoolean, isNumber, isString } from "../../../util/TypeUtils";
describe("asErraiObject", () => {
describe("with objectId filled", () => {
test("with numeric numVal, should return correct a well formed Errai Object", () => {
const input = new NumValBasedErraiObject("com.app.my", 120, "12");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "12",
[ErraiObjectConstants.NUM_VAL]: 120
});
});
test("with boolean numVal, should return correct a well formed Errai Object", () => {
const input = new NumValBasedErraiObject("com.app.my", false, "13");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "13",
[ErraiObjectConstants.NUM_VAL]: false
});
});
test("with string numVal, should return correct a well formed Errai Object", () => {
const input = new NumValBasedErraiObject("com.app.my", "str", "14");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "14",
[ErraiObjectConstants.NUM_VAL]: "str"
});
});
});
describe("with objectId not filled", () => {
test("with numeric numVal, should return correct a well formed Errai Object applying objId's default", () => {
const input = new NumValBasedErraiObject("com.app.my", 120);
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "-1",
[ErraiObjectConstants.NUM_VAL]: 120
});
});
test("with boolean numVal, should return correct a well formed Errai Object applying objId's default", () => {
const input = new NumValBasedErraiObject("com.app.my", false);
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "-1",
[ErraiObjectConstants.NUM_VAL]: false
});
});
test("with string numVal, should return correct a well formed Errai Object applying objId's default", () => {
const input = new NumValBasedErraiObject("com.app.my", "str");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "-1",
[ErraiObjectConstants.NUM_VAL]: "str"
});
});
});
});
describe("from", () => {
test("with numeric NumVal based errai object instance, should retrieve its data correctly", () => {
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "125",
[ErraiObjectConstants.NUM_VAL]: 1
};
const output = NumValBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.objId).toEqual("125");
expect(isNumber(output.numVal)).toBeTruthy();
expect(output.numVal).toBe(1);
});
test("with boolean NumVal based errai object instance, should retrieve its data correctly", () => {
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "125",
[ErraiObjectConstants.NUM_VAL]: false
};
const output = NumValBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.objId).toEqual("125");
expect(isBoolean(output.numVal)).toBeTruthy();
expect(output.numVal).toBe(false);
});
test("with string NumVal based errai object instance, should retrieve its data correctly", () => {
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "125",
[ErraiObjectConstants.NUM_VAL]: "str"
};
const output = NumValBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.objId).toEqual("125");
expect(isString(output.numVal)).toBeTruthy();
expect(output.numVal).toBe("str");
});
});
================================================
FILE: appformer-js/src/marshalling/model/__tests__/ValueBasedErraiObject.test.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
import { NumValBasedErraiObject } from "../NumValBasedErraiObject";
import { ErraiObjectConstants } from "../ErraiObjectConstants";
import { ValueBasedErraiObject } from "../ValueBasedErraiObject";
describe("asErraiObject", () => {
describe("with objectId filled", () => {
test("with string value, should return correct a well formed Errai Object", () => {
const input = new ValueBasedErraiObject("com.app.my", "bla", "12");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "12",
[ErraiObjectConstants.VALUE]: "bla"
});
});
test("with ErraiObject value, should return correct a well formed Errai Object", () => {
const innerVal = new NumValBasedErraiObject("com.app.my", false, "2").asErraiObject();
const input = new ValueBasedErraiObject("my.fqcn", innerVal, "13");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "my.fqcn",
[ErraiObjectConstants.OBJECT_ID]: "13",
[ErraiObjectConstants.VALUE]: {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "2",
[ErraiObjectConstants.NUM_VAL]: false
}
});
});
});
describe("with objectId not filled", () => {
test("with string value, should return correct a well formed Errai Object applying objId's default", () => {
const input = new ValueBasedErraiObject("com.app.my", "bla");
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "-1",
[ErraiObjectConstants.VALUE]: "bla"
});
});
test("with ErraiObject value, should return correct a well formed Errai Object applying objId's default", () => {
const innerVal = new NumValBasedErraiObject("com.app.my", false, "2").asErraiObject();
const input = new ValueBasedErraiObject("my.fqcn", innerVal);
expect(input.asErraiObject()).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "my.fqcn",
[ErraiObjectConstants.OBJECT_ID]: "-1",
[ErraiObjectConstants.VALUE]: {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "2",
[ErraiObjectConstants.NUM_VAL]: false
}
});
});
});
});
describe("from", () => {
test("with string Value based errai object instance, should retrieve its data correctly", () => {
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "125",
[ErraiObjectConstants.VALUE]: "str"
};
const output = ValueBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.objId).toEqual("125");
expect(output.value).toBe("str");
});
test("with ErraiObject Value based errai object instance, should retrieve its data correctly", () => {
const innerVal = new NumValBasedErraiObject("com.app.my", false, "2").asErraiObject();
const input = {
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "125",
[ErraiObjectConstants.VALUE]: innerVal
};
const output = ValueBasedErraiObject.from(input);
expect(output.encodedType).toEqual("com.app.my");
expect(output.objId).toEqual("125");
expect(output.value).toStrictEqual({
[ErraiObjectConstants.ENCODED_TYPE]: "com.app.my",
[ErraiObjectConstants.OBJECT_ID]: "2",
[ErraiObjectConstants.NUM_VAL]: false
});
});
});
================================================
FILE: appformer-js/src/util/DomUtils.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export const AfComponentAttr = "af-js-component";
export function findChildContainers(container: HTMLElement): HTMLElement[] {
const searchResult = searchChildren({
root: container,
stopWhen: (elem: any) => Boolean(getAfComponentAttr(elem)),
accept: (elem: any) => Boolean(getAfComponentAttr(elem))
});
return searchResult.accepted;
}
const flatten = (arr: T[][]) => ([] as T[]).concat(...arr);
function searchParents(args: {
accept: (elem: HTMLElement) => boolean;
stop: (elem: HTMLElement) => boolean;
element: HTMLElement;
}) {
let parent = args.element.parentElement;
while (parent) {
if (args.stop(parent)) {
return args.accept(parent);
}
parent = parent.parentElement;
}
return false;
}
function searchChildren(args: {
root: HTMLElement;
stopWhen: (elem: HTMLElement) => boolean;
accept: (elem: HTMLElement) => boolean;
}) {
const { root, stopWhen, accept } = args;
let node: any;
const stack = [root];
stack.push(root);
const accepted = new Set();
const visited = new Set();
while (stack.length > 0) {
node = stack.pop()!;
if (node !== root && node instanceof HTMLElement && stopWhen(node)) {
if (accept(node)) {
accepted.add(node);
}
visited.add(node);
} else if (node.children && node.children.length) {
for (const child of node.children) {
stack.push(child);
}
}
}
return {
visited: Array.from(visited),
accepted: Array.from(accepted)
};
}
function getAfComponentAttr(container: HTMLElement) {
return container.getAttribute(AfComponentAttr);
}
================================================
FILE: appformer-js/src/util/NumberUtils.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export class NumberUtils {
public static readonly nonNegativeIntegerRegex = new RegExp(/^\d*$/);
public static readonly integerNumberRegex = new RegExp(/^(-)?\d*$/);
public static readonly floatNumberRegex = new RegExp(/^(-)?(\d*)(\.)?(\d*)$/);
public static isNonNegativeIntegerString(str: string): boolean {
return this.nonNegativeIntegerRegex.test(str);
}
public static isIntegerString(str: string): boolean {
return this.integerNumberRegex.test(str);
}
public static isFloatString(str: string): boolean {
return this.floatNumberRegex.test(str);
}
}
================================================
FILE: appformer-js/src/util/TypeUtils.ts
================================================
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
export function isString(obj: any): boolean {
return typeof obj === "string" || obj instanceof String;
}
export function instanceOfString(obj: any): obj is string {
return isString(obj);
}
export function isArray(obj: any): boolean {
return obj instanceof Array;
}
export function instanceOfArray