ArchUnit case insensitive name matching - kotlin

I'm trying to setup tests with Arch Unit to test my naming conventions, following the official examples.
It seems ArchUnit's naming assertions are case sensitive, which is bothering me.
I want to test that no classes in the package domain.service contains the word service.
Given a class domain.service.FileSystemService:
This test passes:
#ArchTest
val domain_service_should_not_have_names_containing_service: ArchRule =
noClasses()
.that().resideInAPackage("..domain.service..")
.should().haveSimpleNameContaining("service")
This test fails:
#ArchTest
val domain_service_should_not_have_names_containing_service: ArchRule =
noClasses()
.that().resideInAPackage("..domain.service..")
.should().haveSimpleNameContaining("Service")
Am I missing something? Is there a way to make ArchUnit's comparisons case insensitive?

If you don't want to use haveNameMatching as proposed in the comments you can also create your own ArchConditions.
public static ArchCondition<JavaClass> containName(String namePart) {
return new NameContains(namePart);
}
private static class NameContains extends ArchCondition<JavaClass> {
private String namePart;
NameContains(String namePart) {
super("contain '" + namePart + "' in the name");
this.namePart = namePart;
}
#Override
public void check(JavaClass javaClass, ConditionEvents events) {
boolean containsName = javaClass.getSimpleName().toLowerCase().contains(namePart.toLowerCase());
String message;
if (containsName) {
message = createCheckMessage(javaClass, "contains '" + namePart + "' in the name");
} else {
message = createCheckMessage(javaClass, "does not contain '" + namePart + "' in the name");
}
events.add(new SimpleConditionEvent(javaClass, containsName, message));
}
}
// taken from com.tngtech.archunit.lang.conditions.ArchConditions
public static <T extends HasDescription & HasSourceCodeLocation> String createCheckMessage(T object,
String message) {
return object.getDescription() + " " + message + " in " + object.getSourceCodeLocation();
}
You can use it like this:
rules.add(noClasses().that().resideInAPackage("..domain.service..").should(containName("Service")));

Related

How can I get Annotation class from TypeDescription

I'm trying to work with ByteBuddy.
How, with given TypeDescription, can I get annotation class?
So far I found getActualName.
#Override
public boolean matches(final TypeDescription target) {
//System.out.printf("matches(%1$s)\n", target);
//System.out.printf("\tcanonicalName: %1$s\n", target.getCanonicalName());
//System.out.printf("\tcomponentType: %1$s\n", target.getComponentType());
{
final AnnotationList inheritedAnnotations = target.getInheritedAnnotations();
inheritedAnnotations.forEach(v -> {
//System.out.printf("\tinherited annotationDescriptor: %1$s\n", v);
});
}
{
final AnnotationList declaredAnnotations = target.getDeclaredAnnotations();
declaredAnnotations.forEach(v -> {
//System.out.printf("\tdeclared annotationDescriptor: %1$s\n", v);
});
}
{
final FieldList<FieldDescription.InDefinedShape> declaredFields = target.getDeclaredFields();
declaredFields.forEach(declaredFiled -> {
System.out.println("declaredField: " + declaredFiled);
final AnnotationList declaredAnnotations = declaredFiled.getDeclaredAnnotations();
declaredAnnotations.forEach(declaredAnnotation -> {
System.out.println("declaredAnnotation: {}" + declaredAnnotation);
final Set<ElementType> elementTypes = declaredAnnotation.getElementTypes();
System.out.println("\telementTypes: " + elementTypes);
final TypeDescription annotationType = declaredAnnotation.getAnnotationType();
System.out.println("\tannotationType: " + annotationType);
System.out.println("\tannotationType.actualName: " + annotationType.getActualName());
});
});
}
return false;
}
I'm, actually, trying to add some methods on compiled classes by some fields annotated with specific annotation.
An AnnotationList is a list of AnnotationDescription typed object where you can invoke the getAnnotationType method to receive a TypeDescription of their annotation type.

Get result of Database.SqlQuery

I´ve a MVC 5 Project in VS 2013 with ODP.net Connection to an oracle database and entity framework 6.
I also have a view in my database which holds all information I need for my select call. I need to get all the information out of the database and display it on the webpage. I get the right number of elements in my list, but they are all empty.
I´ve read that my objects have to contain the correct names of the elements, but that isn´t working.
public class HomeController : Controller
{
public ActionResult Index()
{
using (var context = new DatabaseEntities())
{
var result =
context.Database.SqlQuery<MyEntity>(
"SELECT (case when HERKUNFT = 'AVZ' then ANLA_NR else LAG_NR end) \"LagerAnlage\", " +
"STO_NR \"Standort\", " +
"ART_NR \"Artikelnummer\", " +
"ART_KBEZ || '\n' || ART_BEZ1 || '\n' || ART_BEZ2 \"Artikelbezeichnung\", " +
"SN \"SN\", " +
"TO_CHAR(DTZUGANG, 'DD.MM.YYYY') \"Zugangsdatum\", " +
"TO_CHAR(DTABGANG, 'DD.MM.YYYY') \"Abgangsdatum\", " +
"WERT \"WertStk\", " +
"MENGE \"Stk\" " +
"FROM view_useravz " +
"WHERE user_cd = 'USERNAME' " +
"ORDER BY DTZUGANG");
var list = result.ToList();
}
return View();
}
}
class MyEntity
{
public string LagerAnlage;
public string Standort;
public string Artikelnummer;
public string Artikelbezeichnung;
public string SN;
public string Zugangsdatum;
public string Abgangsdatum;
public string WertStk;
public string Stk;
}
I don´t know why, but now I got an Error and was able to find a solution.
I chose the wrong types in my Class. When i set WertStk and Stk to int everything worked.

How to send Keys.Tab as a parameter to a function

I have a code as below:
void someFunc(){
driver.findElement(By.xpath(OR.getProperty("Nodes_AddNodeDescriptionInput"))).sendKeys(Keys.TAB);
}
which sends a key Tab to the xPath mentioned.
But i want to avoid driver...details in that someFunc(), so I want to have a code which replaces the above code with the below one.
if(!sendKeyboardKeysByXpath("Nodes_AddNodeDescriptionInput", Keys.TAB)) {
printError("Failed to send the Tab key.");
return(false);
}
Def for sendKeyboardKeysByXpath:
public static boolean sendKeyboardKeysByXpath(String xPathKey, CharSequence... textToType) {
printLogs("Calling sendKeyboardKeysByXpath with values: " + xPathKey + ", " + textToType);
try {
printLogs("Typing '"+ textToType + "' to " + xPathKey);
if(!checkElementPresenceByXpath(xPathKey)) {
printFunctionReturn(fn_fail);
return(false);
}
driver.findElement(By.xpath(OR.getProperty(xPathKey))).clear();
driver.findElement(By.xpath(OR.getProperty(xPathKey))).sendKeys(textToType);
}
catch(Throwable t) {
ErrorUtil.addVerificationFailure(t);
printError("sendKeysByXpath: Exception occurred while typing keys.");
printFunctionReturn(fn_fail);
return(false);
}
return(true);
}
How to send the Keys.Tab as a parameter. I am getting garbage value in sendKeyboardKeysByXpath function
Use Keys.TAB.name() it will write TAB
So in your log method it would be textToType.name()

jackson custom serialization with filtering

I need to customize serialization of a POJO in Jackson so that I can apply filter on the properties based on user input
I applied the following annotations on the POJO.
#JsonFilter("userFilter")
#JsonSerialize(using = UserSerializer.class)
The custom serializer class is as below.
public class UserSerializer extends JsonSerializer<User> {
#Override
public void serialize(User value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider sfp = new SimpleFilterProvider();
// create a set that holds name of User properties that must be serialized
Set userFilterSet = new HashSet<String>();
userFilterSet.add("firstName");
userFilterSet.add("corporateOrgs");
userFilterSet.add("rights");
userFilterSet.add("requirements");
sfp.addFilter("userFilter",SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));
// create an objectwriter which will apply the filters
ObjectWriter writer = mapper.writer(sfp);
String json = writer.writeValueAsString(value);
}
}
I can see that Jackson is trying to serialize the POJO using the custom serializer defined. However it ends up in infinite recursion/stackoverflow as writer.writeValueAsString(value) ends up calling the custom serializer again.
Obviously I have not got some basic stuff right here. If the filtering is done outside the serialize method (for example in a method called from main() ), filtering works as expected.
can anyone please provide insight/link to documentation on how to make use of custom serialization to leverage filtering.
Fields can be filtered out with JsonFilter, or you can create a custom JsonSerialize serializer that writes out only certain fields.
Independent of the use of a JsonFilter, the attempt to recursively reserialize the same object to be serialized (first parameter of the overwritten serialize method) in a user-defined serializer with an object mapper will result in an infinite loop. Instead, in a custom serializer you would rather use the JsonGenerator methods (second parameter of the overridden serialize method) to write out field name/values.
In the following answer both variants (#JsonFilter and #JsonSerialize) are demonstrated, where only a part of the available fields are serialized to JSON.
#JsonFilter
To apply filters to properties based on user input, you do not need to extend JsonSerializer. Instead, you annotate the POJO with JsonFilter and just apply the filtering.
A self-contained example based on your code would look like this:
package com.software7.test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Main m = new Main();
try {
m.serialize();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
void serialize() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider sfp = new SimpleFilterProvider();
Set<String> userFilterSet = new HashSet<>();
userFilterSet.add("firstName");
userFilterSet.add("corporateOrgs");
userFilterSet.add("rights");
userFilterSet.add("requirements");
sfp.addFilter("UserFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));
mapper.setFilterProvider(sfp);
User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
"some", "superfluous", "properties");
System.out.println(user);
System.out.println(">>>> serializing >>>>");
String s = mapper.writeValueAsString(user);
System.out.println(s);
}
}
User POJO
package com.software7.test;
import com.fasterxml.jackson.annotation.JsonFilter;
#JsonFilter("UserFilter")
public class User {
public String lastName;
public String firstName;
public String corporateOrgs;
public String rights;
public String requirements;
public String a, b, c;
public User(String lastName, String firstName, String corporateOrgs, String rights, String requirements,
String a, String b, String c) {
this.lastName = lastName;
this.firstName = firstName;
this.corporateOrgs = corporateOrgs;
this.rights = rights;
this.requirements = requirements;
this.a = a;
this.b = b;
this.c = c;
}
#Override
public String toString() {
return "User{" +
"lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
", corporateOrgs='" + corporateOrgs + '\'' +
", rights='" + rights + '\'' +
", requirements='" + requirements + '\'' +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
'}';
}
}
Test
The debug output of the above program would look like this:
User{lastName='Brownrigg', firstName='Don', corporateOrgs='none', rights='+rwx', requirements='n/a', a='some', b='superfluous', c='properties'}
>>>> serializing >>>>
{"firstName":"Don","corporateOrgs":"none","rights":"+rwx","requirements":"n/a"}
The test is successful! As you can see, the properties lastName, a, b and c are removed.
#JsonSerialize Alternative
If you want to use a customer serializer instead you can do like so:
Replace the annotation:
#JsonFilter("UserFilter")
with
#JsonSerialize(using = UserSerializer.class)
but do not use both.
The UserSerializer class could look like this:
package com.software7.test;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class UserSerializer extends JsonSerializer<User> {
#Override
public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField("firstName", user.firstName);
jsonGenerator.writeObjectField("corporateOrgs", user.corporateOrgs);
jsonGenerator.writeObjectField("rights", user.rights);
jsonGenerator.writeObjectField("requirements", user.requirements);
jsonGenerator.writeEndObject();
}
}
Finally, the serialization method would look like this:
void serialize() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
"some", "superfluous", "properties");
System.out.println(user);
System.out.println(">>>> serializing >>>>");
String s = mapper.writeValueAsString(user);
System.out.println(s);
}
The result would be the same in this example. Which variant is better suited depends on the specific use case or personal preferences.

Creating a multi-table SQL database in android

I'm trying to create a multi-table database for my android application. I'm following the suggestion given on this site http://androidforbeginners.blogspot.com/2010/01/creating-multiple-sqlite-database.html for doing it. I keep on getting the error below. The error seems to be cause by the onCreate of the databaes tables.
If you look at my onCreate in the the DBHelper class I have two commented out. This allows it to work no matter which one is left uncommeted.
There has to be a way to create a multi-table database because a single table in a database almost defeats the purpose of having a database.
10-23 02:11:35.383: ERROR/AndroidRuntime(300): Caused by: android.database.sqlite.SQLiteException: Can't upgrade read-only database from version 0 to 1: /data/data/com.parkingticket/databases/Tickets.db
Thanks in advance.
Here is my code
package com.parkingticket;
import java.sql.SQLException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class TicketDBAdapter
{
private static final String DATABASE_NAME="Tickets.db";
private static final int DATABASE_VERSION = 1;
private static final String PARKEDCARS_TABLE = "ParkedCars";
private static final String PARKINGMETERS_TABLE = "ParkingMeters";
private static final String PARKINGTICKETS_TABLE = "ParkingTickets";
private static final String POLICEOFFICERS_TABLE = "PoliceOfficers";
// The name and column index for each column in PARKEDCARS
public static final String KEY_CARID = "carID";
public static final int CARID_COLUMN = 0;
public static final String KEY_CARMAKE = "Make";
public static final int CARMAKE_COLUMN = 1;
public static final String KEY_CARMODEL = "Model";
public static final int CARMODEL_COLUMN = 2;
public static final String KEY_CARCOLOR = "Color";
public static final int CARCOLOR_COLUMN = 3;
public static final String KEY_CARLICENSENUMBER = "LicenseNumber";
public static final int CARLICENSENUMBER_COLUMN = 4;
public static final String KEY_CARMINUTESPARKED = "MinutesParked";
public static final int CARMINUTESPARKED_COLUMN = 5;
// The name and column index for each column in PARKINGMETERS
public static final String KEY_METERID = "meterID";
public static final int METERID_COLUMN = 0;
public static final String KEY_MINUTESPURCHASED = "MinutesPurchased";
public static final int MINUTESPURCHASED_COLUMN = 1;
// The name and column index for each column in PARKINGTICKETS
//TODO create the columns and indexs for parking tickets
// The name and column index for each column in POLICEOFFICERS
public static final String KEY_OFFICERID = "officerID";
public static final int OFFICERID_COLUMN = 0;
public static final String KEY_OFFICERNAME = "Name";
public static final int OFFICERNAME_COLUMN = 1;
public static final String KEY_OFFICERBADGE = "BadgeNumber";
public static final int OFFICERBADE_COLUMN = 2;
//Variable to hold the database instance
private SQLiteDatabase ticketDB;
//Context of the application using the database.
private final Context context;
//Database open/upgrade helper
private TicketDBHelper ticketDBHelper;
public TicketDBAdapter(Context _context)
{
context = _context;
ticketDBHelper = new TicketDBHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void open() throws SQLiteException
{
try
{
ticketDB = ticketDBHelper.getWritableDatabase();
}
catch(SQLiteException ex)
{
ticketDB = ticketDBHelper.getReadableDatabase();
}
}
public void close()
{
ticketDB.close();
}
//Insert a new ParkedCar
public long insertParkedCar(ParkedCar _car)
{
//Create a new row of values to insert
ContentValues newParkedCarValues = new ContentValues();
//Assign values for each row
newParkedCarValues.put(KEY_CARMAKE, _car.getMake());
newParkedCarValues.put(KEY_CARMODEL, _car.getModel());
newParkedCarValues.put(KEY_CARCOLOR, _car.getColor());
newParkedCarValues.put(KEY_CARLICENSENUMBER, _car.getLicenseNumber());
newParkedCarValues.put(KEY_CARMINUTESPARKED, _car.getMinutesParked());
//Insert the row
return ticketDB.insert(PARKEDCARS_TABLE, null, newParkedCarValues);
}
//Remove a ParkedCar based on its index
public boolean removeParkedCar(long _rowIndex)
{
return ticketDB.delete(PARKEDCARS_TABLE, KEY_CARID + "=" + _rowIndex, null)>0;
}
//Update a ParkedCar's MinutesParked
//TODO Create an update for ParkedCar's minutesParked.
public Cursor getAllParkedCarsCursor()
{
return ticketDB.query(PARKEDCARS_TABLE, new String[] {KEY_CARID, KEY_CARMAKE, KEY_CARMODEL, KEY_CARCOLOR, KEY_CARLICENSENUMBER, KEY_CARMINUTESPARKED}, null, null, null, null, null);
}
public Cursor setCursorParkedCar(long _rowIndex) throws SQLException
{
Cursor result = ticketDB.query(true, PARKEDCARS_TABLE, new String []{KEY_CARID}, KEY_CARID + "=" + _rowIndex, null, null, null, null, null);
if ((result.getCount() == 0) || !result.moveToFirst())
{
throw new SQLException("No ParkedCar found for row: " + _rowIndex);
}
return result;
}
public static class TicketDBHelper extends SQLiteOpenHelper
{
public TicketDBHelper(Context context, String name, CursorFactory factory, int version)
{
super(context, name, factory, version);
}
//SQL Statement to create PARKEDCARS table
private static final String PARKEDCARS_CREATE = "create table " + PARKEDCARS_TABLE + " (" + KEY_CARID + " integer primary key autoincrement, " + KEY_CARMAKE + " text not null," + KEY_CARMODEL + " text not null," + KEY_CARCOLOR + " text not null," + KEY_CARLICENSENUMBER + " text not null," + KEY_CARMINUTESPARKED + "int not null);";
//SQL Statement to create ParkingMeters table
private static final String PARKINGMETERS_CREATE = "create table" + PARKINGMETERS_TABLE + " (" + KEY_METERID + " integer primary key autoincrement, " + KEY_MINUTESPURCHASED + " int not null);";
//SQL Statement to create ParkingTickets table
//TODO create the statement for parkingTickets
//SQL Statement to create PoliceOfficers table
private static final String POLICEOFFICERS_CREATE = "create table" + POLICEOFFICERS_TABLE + " (" + KEY_OFFICERID + " integer primary key autoincrement, " + KEY_OFFICERNAME + " text not null," + KEY_OFFICERBADGE + "text not null);";
//Called when no database exists in disk and the helper class needs to create a new one.
#Override
public void onCreate(SQLiteDatabase _db)
{
//_db.execSQL(PARKEDCARS_CREATE);
_db.execSQL(PARKINGMETERS_CREATE);
//_db.execSQL(POLICEOFFICERS_CREATE);
}
//Called when there is a database verion mismatch meaning that the version of the database on disk needs to be upgraded to the current version
#Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion)
{
//Log the version upgrade.
Log.w("TaskDBAdapter", "Upgrading from version " + _oldVersion + " to " + _newVersion + ", which will destroy all old data");
//Upgrade the existing database to conform to the new version
//Multiple previous versions can be handled by comparing _oldVersoin and _newVersion values
//The simplest case is to drop teh old table and create a new one.
_db.execSQL("DROP TABLE IF EXISTS " + PARKEDCARS_TABLE);
_db.execSQL("DROP TABLE IF EXISTS " + PARKINGMETERS_TABLE);
_db.execSQL("DROP TABLE IF EXISTS " + POLICEOFFICERS_TABLE);
onCreate(_db);
}
}
}
I know I'm late,but i think it may help others reading this post.
I had the same problem and it's about spaces,be very careful when you're writing SQL queries about spaces.For example in the code above,you can notice that there's no space in the end :
KEY_OFFICERBADGE + "text not null"
So basically,you have declared a column with no type.
Hope it helped.
Put a Log statement in your open() method when you catch the SQLiteException to see if ticketDBHelper.getWritableDatabase() is failing and subsequently calling ticketDBHelper.getReadableDatabase(), which as the name implies, opens the database as read-only.
I have written a multi table app which works fine. Sounds like you may have a problem opening the existing db file for writing. I would suggest deleting that from your emulator/device, incrementing the version number and rerunning the app. My open method is pasted here.
public DbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
Anthony Nolan
I have found a solution to the problem but not a direct answer on this site.
http://pheide.com/page/11/tab/24#post13
Why using a abstract class to create the databases the extending that class works I can't figure out for the life of me because it seems I'm doing the same thing in my one class up above. None the less it works as far as I've played around with it.