/* * Copyright 2014 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.kie.workbench.common.widgets.client.datamodel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.enterprise.inject.Instance; import org.drools.workbench.models.datamodel.imports.Import; import org.drools.workbench.models.datamodel.imports.Imports; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.FieldAccessorsAndMutators; import org.drools.workbench.models.datamodel.oracle.MethodInfo; import org.drools.workbench.models.datamodel.oracle.ModelField; import org.drools.workbench.models.datamodel.oracle.OperatorsOracle; import org.jboss.errai.common.client.api.Caller; import org.jboss.errai.common.client.api.ErrorCallback; import org.jboss.errai.common.client.api.RemoteCallback; import org.jboss.errai.validation.client.dynamic.DynamicValidator; import org.junit.Before; import org.junit.Test; import org.kie.workbench.common.services.datamodel.model.LazyModelField; import org.kie.workbench.common.services.datamodel.model.PackageDataModelOracleIncrementalPayload; import org.kie.workbench.common.services.datamodel.service.IncrementalDataModelService; import org.mockito.Mock; import org.uberfire.backend.vfs.Path; import org.uberfire.client.callbacks.Callback; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class AsyncPackageDataModelOracleImplTest { private AsyncPackageDataModelOracle oracle; private PackageDataModelOracleIncrementalPayload personPayload; private PackageDataModelOracleIncrementalPayload addressPayload; private PackageDataModelOracleIncrementalPayload giantPayload; private PackageDataModelOracleIncrementalPayload stringPayload; private PackageDataModelOracleIncrementalPayload defaultPayload; @Mock private Instance<DynamicValidator> validatorInstance; @Before public void setUp() throws Exception { AsyncPackageDataModelOracle oracle = new AsyncPackageDataModelOracleImpl( new Service(), validatorInstance ); personPayload = createPersonPayload(); addressPayload = createAddressPayload(); giantPayload = createGiantPayload(); stringPayload = createStringPayload(); defaultPayload = createDefaultPayload(); oracle.addGlobals( createGlobals() ); oracle.setPackageName( "org" ); oracle.addModelFields( createProjectModelFields() ); oracle.addMethodInformation( createProjectMethodInformation() ); oracle.addSuperTypes( createSuperTypes() ); oracle.addPackageNames( createPackageNames() ); oracle.filter( createImports() ); this.oracle = oracle; } private Map<String, List<MethodInfo>> createProjectMethodInformation() { HashMap<String, List<MethodInfo>> map = new HashMap<String, List<MethodInfo>>(); map.put( "org.globals.GiantContainerOfInformation", Collections.EMPTY_LIST ); ArrayList<MethodInfo> stringMethodInfos = new ArrayList<MethodInfo>(); ArrayList<String> valueOfParams = new ArrayList<String>(); valueOfParams.add( "Integer" ); stringMethodInfos.add( new MethodInfo( "valueOf", valueOfParams, "java.lang.String", null, "String" ) ); map.put( "java.lang.String", stringMethodInfos ); ArrayList<MethodInfo> personMethodInfos = new ArrayList<MethodInfo>(); ArrayList<String> build1Params = new ArrayList<String>(); build1Params.add( "String" ); build1Params.add( "Integer" ); personMethodInfos.add( new MethodInfo( "build", build1Params, "org.test.Person", null, null ) ); ArrayList<String> getNameParams = new ArrayList<String>(); personMethodInfos.add( new MethodInfo( "getName", getNameParams, "java.lang.String", null, null ) ); ArrayList<String> build2Params = new ArrayList<String>(); build2Params.add( "String" ); personMethodInfos.add( new MethodInfo( "build", build2Params, "org.test.Person", null, null ) ); ArrayList<String> build3Params = new ArrayList<String>(); build3Params.add( "Integer" ); personMethodInfos.add( new MethodInfo( "build", build3Params, "org.test.Person", null, null ) ); map.put( "org.test.Person", personMethodInfos ); return map; } private HashMap<String, ModelField[]> createProjectModelFields() { HashMap<String, ModelField[]> map = new HashMap<String, ModelField[]>(); map.put( "org.test.Person", new ModelField[]{ getLazyThisField( "org.test.Person" ) } ); map.put( "java.lang.String", new ModelField[]{ getLazyThisField( "java.lang.String" ) } ); map.put( "org.Address", new ModelField[]{ getLazyThisField( "org.Address" ) } ); map.put( "org.Document", new ModelField[]{ getLazyThisField( "org.Document" ) } ); map.put( "org.globals.GiantContainerOfInformation", new ModelField[]{ getLazyThisField( "org.globals.GiantContainerOfInformation" ) } ); return map; } private Imports createImports() { Imports imports = new Imports(); imports.addImport( new Import( "org.test.Person" ) ); imports.addImport( new Import( "java.lang.String" ) ); imports.addImport( new Import( "org.globals.GiantContainerOfInformation" ) ); return imports; } private PackageDataModelOracleIncrementalPayload createDefaultPayload() { return new PackageDataModelOracleIncrementalPayload(); } private PackageDataModelOracleIncrementalPayload createGiantPayload() { PackageDataModelOracleIncrementalPayload payload = new PackageDataModelOracleIncrementalPayload(); HashMap<String, ModelField[]> addressModelFields = new HashMap<String, ModelField[]>(); addressModelFields.put( "org.globals.GiantContainerOfInformation", new ModelField[]{ new ModelField( "this", "org.globals.GiantContainerOfInformation", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.SELF, FieldAccessorsAndMutators.ACCESSOR, "this" ) } ); payload.setModelFields( addressModelFields ); return payload; } private PackageDataModelOracleIncrementalPayload createStringPayload() { PackageDataModelOracleIncrementalPayload payload = new PackageDataModelOracleIncrementalPayload(); HashMap<String, ModelField[]> addressModelFields = new HashMap<String, ModelField[]>(); addressModelFields.put( "java.lang.String", new ModelField[]{ new ModelField( "this", "java.lang.String", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.SELF, FieldAccessorsAndMutators.ACCESSOR, "this" ) } ); payload.setModelFields( addressModelFields ); return payload; } private PackageDataModelOracleIncrementalPayload createAddressPayload() { PackageDataModelOracleIncrementalPayload payload = new PackageDataModelOracleIncrementalPayload(); HashMap<String, ModelField[]> addressModelFields = new HashMap<String, ModelField[]>(); addressModelFields.put( "org.Address", new ModelField[]{ new ModelField( "this", "org.Address", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.SELF, FieldAccessorsAndMutators.ACCESSOR, "this" ), new ModelField( "street", "String", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.DECLARED, FieldAccessorsAndMutators.BOTH, DataType.TYPE_STRING ), new ModelField( "homeAddress", "Boolean", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.DECLARED, FieldAccessorsAndMutators.BOTH, DataType.TYPE_BOOLEAN ), new ModelField( "number", Integer.class.getName(), ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.DECLARED, FieldAccessorsAndMutators.BOTH, DataType.TYPE_NUMERIC_INTEGER )} ); payload.setModelFields( addressModelFields ); return payload; } private PackageDataModelOracleIncrementalPayload createPersonPayload() { PackageDataModelOracleIncrementalPayload payload = new PackageDataModelOracleIncrementalPayload(); HashMap<String, ModelField[]> personModelFields = new HashMap<String, ModelField[]>(); personModelFields.put( "org.test.Person", new ModelField[]{ new ModelField( "this", "org.test.Person", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.SELF, FieldAccessorsAndMutators.ACCESSOR, "this" ), new ModelField( "address", "org.Address", ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.DECLARED, FieldAccessorsAndMutators.BOTH, "Address" ) } ); payload.setModelFields( personModelFields ); return payload; } private HashMap<String, String> createGlobals() { HashMap<String, String> globals = new HashMap<String, String>(); globals.put( "giant", "org.globals.GiantContainerOfInformation" ); globals.put( "person", "org.test.Person" ); return globals; } private Map<String, List<String>> createSuperTypes() { Map<String, List<String>> superTypes = new HashMap<String, List<String>>(); superTypes.put( "org.test.Person", Arrays.asList( new String[]{ "org.test.Parent", "org.test.GrandParent" } ) ); superTypes.put( "org.Address", Arrays.asList( new String[]{ "org.Location" } ) ); return superTypes; } private List<String> createPackageNames() { List<String> packageNames = new ArrayList<String>(); packageNames.add( "io.test" ); packageNames.add( "org.test" ); packageNames.add( "com.test" ); return packageNames; } @Test public void testIsFactTypeRecognized() { assertTrue( oracle.isFactTypeRecognized( "org.Address" ) ); } @Test public void testFactTypes() { final String[] types = oracle.getFactTypes(); assertEquals( 5, types.length ); assertEquals( "Address", types[ 0 ] ); assertEquals( "Document", types[ 1 ] ); assertEquals( "GiantContainerOfInformation", types[ 2 ] ); assertEquals( "Person", types[ 3 ] ); assertEquals( "String", types[ 4 ] ); } @Test public void testAllFactTypes() { final String[] types = oracle.getAllFactTypes(); assertEquals( 5, types.length ); assertEquals( "java.lang.String", types[ 0 ] ); assertEquals( "org.Address", types[ 1 ] ); assertEquals( "org.Document", types[ 2 ] ); assertEquals( "org.globals.GiantContainerOfInformation", types[ 3 ] ); assertEquals( "org.test.Person", types[ 4 ] ); } @Test public void testInternalFactTypes() { final String[] types = oracle.getInternalFactTypes(); assertEquals( 2, types.length ); assertEquals( "org.Address", types[ 0 ] ); assertEquals( "org.Document", types[ 1 ] ); } @Test public void testExternalFactTypes() { final String[] types = oracle.getExternalFactTypes(); assertEquals( 3, types.length ); assertEquals( "java.lang.String", types[ 0 ] ); assertEquals( "org.globals.GiantContainerOfInformation", types[ 1 ] ); assertEquals( "org.test.Person", types[ 2 ] ); } @Test public void testName() throws Exception { assertEquals( "org.test.Person", oracle.getFQCNByFactName( "Person" ) ); assertEquals( "Person", oracle.getFieldClassName( "Person", "this" ) ); } @Test public void testGetFieldCompletions() throws Exception { Callback<ModelField[]> callback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { assertEquals( 2, result.length ); assertEquals( "Address", oracle.getFieldType( "Person", "address" ) ); assertEquals( "Address", oracle.getFieldClassName( "Person", "address" ) ); } } ); oracle.getFieldCompletions( "Person", callback ); verify( callback ).callback( any( ModelField[].class ) ); } @Test public void testGetFieldCompletionsForField() throws Exception { Callback<ModelField[]> callback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { assertEquals( 4, result.length ); assertEquals( "Address", oracle.getFieldClassName( "Address", "this" ) ); assertEquals( "this", oracle.getFieldType( "Address", "this" ) ); assertEquals( "String", oracle.getFieldClassName( "Address", "street" ) ); assertEquals( "String", oracle.getFieldType( "Address", "street" ) ); assertEquals( "Boolean", oracle.getFieldClassName( "Address", "homeAddress" ) ); assertEquals( "Boolean", oracle.getFieldType( "Address", "homeAddress" ) ); assertEquals( Integer.class.getName(), oracle.getFieldClassName( "Address", "number" ) ); assertEquals( DataType.TYPE_NUMERIC_INTEGER, oracle.getFieldType( "Address", "number" ) ); } } ); oracle.getFieldCompletions( "Address", callback ); verify( callback ).callback( any( ModelField[].class ) ); } @Test public void testGetOperatorCompletionsForString() throws Exception { Callback<String[]> callback = spy(new Callback<String[]>() { @Override public void callback(String[] result) { assertArrayEquals( new String[] { "==", "!=", "<", ">", "<=", ">=", "matches", "soundslike", "== null", "!= null", "in", "not in" }, result ); } }); oracle.getFieldCompletions( "Address", mock( Callback.class ) ); oracle.getOperatorCompletions( "Address", "street", callback ); verify( callback ).callback( any( String[].class ) ); } @Test public void testGetOperatorCompletionsForInteger() throws Exception { Callback<String[]> callback = spy(new Callback<String[]>() { @Override public void callback(String[] result) { assertArrayEquals( new String[] { "==", "!=", "<", ">", "<=", ">=", "== null", "!= null", "in", "not in" }, result ); } }); oracle.getFieldCompletions( "Address", mock( Callback.class ) ); oracle.getOperatorCompletions( "Address", "number", callback ); verify( callback ).callback( any( String[].class ) ); } @Test public void testGetOperatorCompletionsForBoolean() throws Exception { Callback<String[]> callback = spy(new Callback<String[]>() { @Override public void callback(String[] result) { assertArrayEquals( new String[] { "==", "!=", "== null", "!= null" }, result ); } }); oracle.getFieldCompletions( "Address", mock( Callback.class ) ); oracle.getOperatorCompletions( "Address", "homeAddress", callback ); verify( callback ).callback( any( String[].class ) ); } @Test public void testGetOperatorCompletionsForThis() throws Exception { Callback<String[]> callback = spy(new Callback<String[]>() { @Override public void callback(String[] result) { assertArrayEquals( new String[] { "==", "!=", "== null", "!= null" }, result ); } }); oracle.getFieldCompletions( "Address", mock( Callback.class ) ); oracle.getOperatorCompletions( "Address", "this", callback ); verify( callback ).callback( any( String[].class ) ); } @Test public void testGetFieldCompletionsForSomethingThatDoesNotReturnFields() throws Exception { Callback<ModelField[]> callback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { assertEquals( 0, result.length ); } } ); oracle.getFieldCompletions( "I.do.not.Exist", callback ); verify( callback ).callback( any( ModelField[].class ) ); } @Test public void testGetFieldCompletionsMutators() throws Exception { Callback<ModelField[]> callback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { assertEquals( 3, result.length ); } } ); oracle.getFieldCompletions( "Address", FieldAccessorsAndMutators.MUTATOR, callback ); verify( callback ).callback( any( ModelField[].class ) ); } @Test public void testGetMethodInfosForGlobalVariable() throws Exception { Callback<List<MethodInfo>> callback = spy( new Callback<List<MethodInfo>>() { @Override public void callback( List<MethodInfo> result ) { assertEquals( 0, result.size() ); } } ); oracle.getMethodInfosForGlobalVariable( "giant", callback ); verify( callback ).callback( anyList() ); } @Test public void testGetMethodInfosSortedForGlobalVariable() { Callback<List<MethodInfo>> callback = spy( new Callback<List<MethodInfo>>() { @Override public void callback( List<MethodInfo> result ) { assertEquals( 4, result.size() ); assertEquals( "build", result.get( 0 ).getName() ); assertEquals( 1, result.get( 0 ).getParams().size() ); assertEquals( "Integer", result.get( 0 ).getParams().get( 0 ) ); assertEquals( "build", result.get( 1 ).getName() ); assertEquals( 1, result.get( 1 ).getParams().size() ); assertEquals( "String", result.get( 1 ).getParams().get( 0 ) ); assertEquals( "build", result.get( 2 ).getName() ); assertEquals( 2, result.get( 2 ).getParams().size() ); assertEquals( "String", result.get( 2 ).getParams().get( 0 ) ); assertEquals( "Integer", result.get( 2 ).getParams().get( 1 ) ); assertEquals( "getName", result.get( 3 ).getName() ); assertEquals( 0, result.get( 3 ).getParams().size() ); } } ); oracle.getMethodInfosForGlobalVariable( "person", callback ); verify( callback ).callback( anyList() ); } @Test public void testGetFieldCompletionsForGlobalVariable() throws Exception { Callback<ModelField[]> callback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { assertEquals( 1, result.length ); } } ); oracle.getFieldCompletionsForGlobalVariable( "giant", callback ); verify( callback ).callback( any( ModelField[].class ) ); } @Test public void testGetMethodParamsString() throws Exception { Callback<List<String>> callback = spy( new Callback<List<String>>() { @Override public void callback( List<String> result ) { // In real life this returns 58 values. Using a mock here assertEquals( 1, result.size() ); } } ); oracle.getMethodParams( "String", "valueOf(Integer)", callback ); verify( callback ).callback( anyList() ); } @Test /** * Person is imported, but Person has an address that is not. Asking connective operator completions for Address.street should still work. */ public void testGetConnectiveOperatorCompletions() throws Exception { final Callback<String[]> connectiveOperatorsCallback = spy( new Callback<String[]>() { @Override public void callback( String[] result ) { assertEquals( OperatorsOracle.STRING_CONNECTIVES.length, result.length ); for ( String connective : OperatorsOracle.STRING_CONNECTIVES ) { boolean foundIt = false; for ( String resultConnective : result ) { if ( connective.equals( resultConnective ) ) { foundIt = true; break; } } assertTrue( foundIt ); } } } ); Callback<ModelField[]> fieldCompletionsCallback = spy( new Callback<ModelField[]>() { @Override public void callback( ModelField[] result ) { // We can't really know about the fields of Address before we query them. // This is why we call getFieldCompletions() before getConnectiveOperatorCompletions() oracle.getConnectiveOperatorCompletions( "Address", "street", connectiveOperatorsCallback ); } } ); oracle.getFieldCompletions( "Address", fieldCompletionsCallback ); verify( fieldCompletionsCallback ).callback( any( ModelField[].class ) ); verify( connectiveOperatorsCallback ).callback( any( String[].class ) ); } @Test public void testGetSuperTypes() { Callback<List<String>> getSuperTypesCallback = spy( new Callback<List<String>>() { @Override public void callback( List<String> result ) { assertEquals( 2, result.size() ); assertEquals( "org.test.GrandParent", result.get( 0 ) ); assertEquals( "org.test.Parent", result.get( 1 ) ); } } ); oracle.getSuperTypes( "Person", getSuperTypesCallback ); verify( getSuperTypesCallback ).callback( anyList() ); } @Test public void testGetPackageNames() { List<String> packageNames = oracle.getPackageNames(); assertEquals( 3, packageNames.size() ); assertEquals( "com.test", packageNames.get( 0 ) ); assertEquals( "io.test", packageNames.get( 1 ) ); assertEquals( "org.test", packageNames.get( 2 ) ); } private LazyModelField getLazyThisField( String clazz ) { return new LazyModelField( "this", clazz, ModelField.FIELD_CLASS_TYPE.REGULAR_CLASS, ModelField.FIELD_ORIGIN.SELF, FieldAccessorsAndMutators.ACCESSOR, "this" ); } private class Service implements Caller<IncrementalDataModelService> { private RemoteCallback<PackageDataModelOracleIncrementalPayload> callback; private IncrementalDataModelService service = new IncrementalDataModelService() { @Override public PackageDataModelOracleIncrementalPayload getUpdates( Path resourcePath, Imports imports, String factType ) { if ( factType.equals( "org.test.Person" ) ) { callback.callback( personPayload ); } else if ( factType.equals( "java.lang.String" ) ) { callback.callback( stringPayload ); } else if ( factType.equals( "org.Address" ) ) { callback.callback( addressPayload ); } else if ( factType.equals( "org.globals.GiantContainerOfInformation" ) ) { callback.callback( giantPayload ); } else { callback.callback( defaultPayload ); } return null; } }; @Override public IncrementalDataModelService call() { return service; } @Override public IncrementalDataModelService call( RemoteCallback<?> remoteCallback ) { callback = (RemoteCallback<PackageDataModelOracleIncrementalPayload>) remoteCallback; return service; } @Override public IncrementalDataModelService call( RemoteCallback<?> remoteCallback, ErrorCallback<?> errorCallback ) { callback = (RemoteCallback<PackageDataModelOracleIncrementalPayload>) remoteCallback; return service; } } }