Manipulating a String with substring inside a query builder - java

I have a Query Builder like this:
#Override
public List<ComplementoMaterial> findSomething(String codigoPrestador, String documentoPrestador, String numeroLote, String codDocumento, List<String> codigosServicos) {
return builder().query(sqlComplementos())
.set("codPrestador", codigoPrestador)
.set("docPrestador", documentoPrestador)
.set("numeroLote", numeroLote)
.set("codDocumento", codDocumento)
.set("codServicos", codigosServicos)
.mapper(new RowMapper<ComplementoMaterial>() {
#Override
public ComplementoMaterial mapRow(ResultSet rs, int rowNum) throws SQLException {
ComplementoMaterial c = new ComplementoMaterial();
c.setCodigoServico(rs.getLong("COD_SERVICO"));
c.setRegistroAnvisa(rs.getString("COD_MATERIAL"));
c.setReferencia(rs.getString("COD_REF_MATERIAL"));
c.setAutorizacaoFuncionamento(rs.getString("NUM_AUT_FAT"));
return c;
}
}).executeQuery();
}
When I set the codigosServicos, I wish to apply an substring to him, so for each index I need take just after the 4th char of that String. For example:
If in codigoServicos I have a List as follow ["Michael","Jackson","Lebron"], I need that the query take just ["ael", "son", "on"].
I already tried to add a just codigoServicos.substring(4), but as he is set as List, that is not possible. And I also cannot broke the set to add a for loop.
Any idea do help me?
Tks

Are you using Java 8+? You can do it in one line with streams, like this:
.set("codServicos", codigosServicos.stream().map(s -> s.substring(4)).collect(Collectors.toList()))
Otherwsie you have to use a loop, sorry. You can, of course do the loop before you do set:
#Override
public List<ComplementoMaterial> findSomething(String codigoPrestador, String documentoPrestador, String numeroLote, String codDocumento, List<String> codigosServicos) {
List<String> substrings = new List<>(codigosServicos.size());
for (String name : codigosServicos) {
substrings.add(name.substring(4));
}
return builder().query(sqlComplementos())
.set("codPrestador", codigoPrestador)
.set("docPrestador", documentoPrestador)
.set("numeroLote", numeroLote)
.set("codDocumento", codDocumento)
// add list of substrings instead of the original list
.set("codServicos", substrings)
.mapper(new RowMapper<ComplementoMaterial>() {
#Override
public ComplementoMaterial mapRow(ResultSet rs, int rowNum) throws SQLException {
ComplementoMaterial c = new ComplementoMaterial();
c.setCodigoServico(rs.getLong("COD_SERVICO"));
c.setRegistroAnvisa(rs.getString("COD_MATERIAL"));
c.setReferencia(rs.getString("COD_REF_MATERIAL"));
c.setAutorizacaoFuncionamento(rs.getString("NUM_AUT_FAT"));
return c;
}
}).executeQuery();
}

Related

How would I unit test jdbcTemplate.query that have overrides?

I have a class that uses multiple get methods the returns
public int getCurrNum(String Name) {
// query clearances table to return an int that represents the clearance level
String sql = "SELECT number FROM clearances WHERE '" + Name + "' = name;";
//String.format("SELECT number FROM clearances WHERE '%s' = name;",clearanceName);
return jdbcTemplate.queryForObject(sql, Integer.class);
}
which I understand I can use Mockito with a statement like Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.eq(Integer.class))).thenReturn(1);
But that is not really testing values that are being passed in because I am just telling it to return a value I want. I want to make sure all these methods return what the parameters are specially passing in. We have a user token with user details being sent in. We also have more JdbcTemplates such as
public List<String> getCurr(String currCountry) {
// query alliances table to return a list of alliance tags that countain the
// user's country tag
String sql = "SELECT * FROM user WHERE '" + currCountry + "' = ANY(access_tags) ;";
return jdbcTemplate.query(sql, new RowMapper<String>() {
#Override
public String mapRow(ResultSet rs, int rownumber) throws SQLException {
return rs.getString(1);
}
});
Then the last methods combines everything and has this return statement that uses all these setters from another class.
// return list of appropriately filtered missions
return jdbcTemplate.query(sql, new RowMapper<Mission>() {
#Override
public OtherClass mapRow(ResultSet rs, int rownumber) throws SQLException {
OtherClass m = new OtherClass();
m.setNumber(rs.getInt(1));
m.setName(rs.getString(2));
m.setLastCheckinDate(rs.getString(3));
m.setLocation(rs.getString(4));
m.setCurrLocation(rs.getString(5));
m.setFinalLocation(rs.getString(6));
m.setTags(rs.getString(7));
return m;
}
});
}
But I am not sure how to test these statements. Without using the Mockito.when commands, they always turn out null. We have this information in a database .xml file for the column and rows so it knows what information to grab to fill in the lists. Do I need to mock a mock db or something to test this?

get position with Map context

I'm trying to create a custom Itemreader using a HashMap, here is an eaxmple i find it of an itemReader using a list instead of HashMap
public class InMemoryStudentReader implements ItemReader<StudentDTO> {
private int nextStudentIndex;
private List<StudentDTO> studentData;
InMemoryStudentReader() {
initialize();
}
private void initialize() {
StudentDTO tony = new StudentDTO();
tony.setEmailAddress("tony.tester#gmail.com");
tony.setName("Tony Tester");
tony.setPurchasedPackage("master");
StudentDTO nick = new StudentDTO();
nick.setEmailAddress("nick.newbie#gmail.com");
nick.setName("Nick Newbie");
nick.setPurchasedPackage("starter");
StudentDTO ian = new StudentDTO();
ian.setEmailAddress("ian.intermediate#gmail.com");
ian.setName("Ian Intermediate");
ian.setPurchasedPackage("intermediate");
studentData = Collections.unmodifiableList(Arrays.asList(tony, nick, ian));
nextStudentIndex = 0;
}
#Override
public StudentDTO read() throws Exception {
StudentDTO nextStudent = null;
if (nextStudentIndex < studentData.size()) {
nextStudent = studentData.get(nextStudentIndex);
nextStudentIndex++;
}
return nextStudent;
}
}
As you can see here we can iterate on a list by it's position (index), so when we call next time the method read() we garantie that we get the next elment.
But in my case the is no notion of index, as HashMap has no concept of position so there is no way to get an object by position.
haw can update this code to work with my case:
public class InMemoryMouvementReader implements ItemReader<MouvementFileRow> {
#Autowired
private MouvementToMap mvts;
#Override
public MouvementFileRow read() throws Exception {
MouvementFileRow nextMouvement = null;
// the Map
// public Map<Long, MouvementFileRow> getMouvmentFileRowMap() {
// return mouvmentFileRowMap;
// }
mvts.getMouvmentFileRowMap()
return nextMouvement;
}
}
do i need to change the hashMap to LinkedHashMap instead or to convert map to List ?
There are no indexes like 0, 1, ... n but you can use the keys in an specific order (e.g. alphabetic sort). Another approach is to get a Iterator object by calling yourHashMap.keySet().iterator() and use that object as class-attribute instead of the nextStudentIndex-attribute. Then use a code snippet like:
if (yourIterator.hasNext()) return yourHashMap.get(youtIterator.next());
else return null;
If you don't want to use any kind of index in your implementation, then read(idx) can be written in the loop, where read() is going to be called idx times.

Selenium java testNG: Is it possible to use dataprovider data partially in testng test method

I am new to Page-Object model automation using selenium and java. I am using the Page Object model and have each page as a single class and the actions in that page as methods.Using excel to keep read test data. I have a test for searching for client using various parameters like client number, policy number, surname, firstname, webrefernce, email eand many more...... Now I have to provide all parameters in method signature otherwise test is failing with dataprovider mismatch error. I have a GetData method which provide string array from excelsheet specified.
Is it possible to make parameters optional so that I can specify only the parameters required for that particular test in the test method's signature.? In actual test there are 15 parameters and additional combinations. (If this is not possible, I have to split the data in to 16 different tab and define data providers for each tests separately). Or any other way to achieve this? Thanks
Current code:
#DataProvider(name="ClientSearchData")
public String[][] getTestData() {
String[][] testRecords = getData("TestData_igo4.xlsx","ClientSearch");
return testRecords;
}
#BeforeTest
public void setUp() {
init();
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByClientNumber(String clientnumber, String policynumber, String surname, String webreference, String email) {
//code for search by clientnumber
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByPolicyNumber(String clientnumber, String policynumber, String surname, String webreference, String email) {
//Code for search by policynumber
}
I want something like the following to avoid unnecessary parameters for each tests..
#DataProvider(name="ClientSearchData")
public String[][] getTestData() {
String[][] testRecords = getData("TestData.xlsx","ClientSearch");
return testRecords;
}
#BeforeTest
public void setUp() {
init();
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByClientNumber(String clientnumber) {
//code for search by clientnumber
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByPolicyNumber(String policynumber) {
//Code for search by policynumber
}
I think what you are looking is Varargs.
You can simply do like below
#DataProvider(name = "testData")
public static Object[][] testDataProvider() {
return new Object[][] {new String[]{"a","b","c"}};
}
#Test(priority=3,dataProvider = "testData")
public void test1(String... str1) {
System.out.println("first string"+" "+str1[0]);
}
#Test(priority=4,dataProvider = "testData")
public void test2(String... str2) {
System.out.println("second string"+" " + str2[1]);
}
The above prints
first string a
second string b
In above code just adjust data provider according to your getTestData
Three dots ... is the key here
EDIT:
You can actually do it without Varargs. The below also prints same
#Test(priority=3,dataProvider = "testData")
public void test1(String str1[] ) {
System.out.println("first string"+" "+str1[0]);
}
#Test(priority=4,dataProvider = "testData")
public void test2(String str2[]) {
System.out.println("second string"+" " + str2[1]);
}
You can model your dataprovider based on the method calling it. What I would do is probably write logic based on method name. Pass the Method object to your dataprovider, based on the name of the method, create your Object[][].
say
public Object[][] dp(Method m) {
key = m.getName.replace("verifyClientSearchBy","");
//From excel data, just fetch key column's values or put
//logic here whatever is convenient
//Build your Object[][] with only one value

HibernateCallback returns value even though search criteria is not qualified

I am having a trouble with my codes. If I input correct criteria, let say 300 for the amount it returns correct result/s.But if I put not qualified search criteria it still return result/s which is incorrect.
#Override
public Page<ApPayment> searchPayment(final String searchCriteria,
final PageSetting pageSetting) {
HibernateCallback<Page<ApPayment>> paymentCallBack = new HibernateCallback<Page<ApPayment>>() {
#Override
public Page<ApPayment> doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session.createCriteria(ApPayment.class);
if(!searchCriteria.isEmpty() && StringFormatUtil.isNumeric(searchCriteria)) {
Integer paymentNo = Integer.valueOf(searchCriteria);
Double amount = Double.valueOf(searchCriteria);
criteria.add(Restrictions.or(Restrictions.like(ApPayment.FIELD.paymentNumber.name(), paymentNo), Restrictions.eq(ApPayment.FIELD.amount.name(), amount)));
}
Page<ApPayment> payments = getAll(criteria, pageSetting);
for (ApPayment payment: payments.getData()) {
--some codes--
}
return payments;
}
};
return getHibernateTemplate().execute(paymentCallBack);
}
Thanks in advance.

How can I merge three similar methods with different argument types into one generic one?

I am relatively inexperienced with java & generics, so please excuse me if this is a stupid question.
I have 3 very similar helper methods called verifyTextualSort, verifyNumericSort and verifyDateSort.
The 3 methods follow the same pattern with only a slight difference in them:
private boolean verifyTextualSort(...) {
ArrayList<String> list = new ArrayList<String>();
// Do common stuff with the list
// Do textual-specific stuff
// Do common stuff with the list
}
private boolean verifyNumericSort(...) {
ArrayList<Integer> list = new ArrayList<Integer>();
// Do common stuff with the list
// Do Numeric-specific stuff
// Do common stuff with the list
}
Is there some way I can combine them into one method, passing somehow the type (Integer, String, Date) as a parameter? I have to be able to know which is the type from inside the method so that I can do the correct specific stuff.
You need three method for the specific stuff. However for the common stuff you can create a common method they both call.
private boolean verifyNumericSort(...) {
List<Integer> list = new ArrayList<Integer>();
commonStuff1(list);
// Do Numeric-specific stuff
commonStuff2(list);
}
You could pass a Class as a parameter, if that is what you want (as you said, passing the type as a parameter):
public <T> void test(List<T> l, T t, Class<T> c) {
System.out.println(c.getName());
System.out.println(l.get(0).getClass().getName());
System.out.println(t.getClass().getName());
}
All the sysouts above will print out the name of the class, so you'll be able to choose which one suits you the best.
You can't do that by introspection using the Generics because of type erasure. But if the list is not empty, you can check the type of the first element and then invoke appropriate method.
since you have 3 fields you can do this..
class A
{
private Date date = null;
private Integer int = null;
private String text = null;
//add getters and setters for these fields
}
and now pass this class Object as an arguement to that method
public boolean verify(A a){
a.getDate();
a.getInt()
//etc and do your stuff
}
You need generics and refactoring:
private boolean verifyTextualSort(List<String> strings) {
commonStuffA(strings);
// Do textual-specific stuff
commonStuffB(strings);
return true; // ?
}
private boolean verifyNumericSort(List<Integer> ints) {
commonStuffB(ints);
// Do Numeric-specific stuff
commonStuffB(ints);
return true; // ?
}
private void commonStuffA(List<?> things) { // This method accept a list of anything
// Do common stuff A with the list
}
private void commonStuffB(List<?> things) { // This method accept a list of anything
// Do common stuff B with the list
}
private void someCallingMethod() {
List<String> strings = new ArrayList<String>();
verifyTextualSort(strings);
List<Integer> ints = new ArrayList<Integer>();
verifyTextualSort(ints);
}
I think you could possibly do something similar to this:
public <T extends Object> boolean verify(T t)
{
if(!(t==null))
{
if(t instanceof Date)
{
//Do date verify routine
return true;
}
else if(t instanceof String)
{
//Do String verify routine
return true;
}
else
{
//Do default verify routine which could be Integer
return true;
}
}
return false;
}
NOTE:
This is not tested.
As others have mentioned, you can't do that with generics because of type erasure (see the other answers for a link to type erasure). I believe you can get a reasonable solution (without instanceof) with polymorphism. Here is an example:
public class VerifySort
{
public static void main(String[] args)
{
VerifySort verifySort = new VerifySort();
Date testDate = new Date();
Integer testInteger = 17;
String testString = "Blammy";
verifySort.verify(testString);
verifySort.verify(testInteger);
verifySort.verify(testDate);
}
private boolean verify(Date parameter)
{
SimpleDateFormat dateFormat = new SimpleDateFormat();
System.out.print("Date parameter: ");
System.out.println(dateFormat.format(parameter));
return true;
}
private boolean verify(Integer parameter)
{
System.out.print("Integer parameter: ");
System.out.println(parameter);
return true;
}
private boolean verify(String parameter)
{
System.out.print("String parameter: ");
System.out.println(parameter);
return true;
}

Categories

Resources