csv to pojo with another pojo - opencsv

Orgnization{
private String name;
private String uniqueId;
private boolean selfRegEnabled;
private List<Address> addrList;
public void setAddress(Address a){..}
public void setName(String name){..}
}
Addess{
private String type;
private String line1;
private String line2;
private String line3;
private String city;
private String state;
private String zip;
private String country;
}
CSV Header Columns are as below
System.UniqueID,Name,EnableSelf-Registration,Addr1.Type,Addr1.Line1,Addr1.Line2,Addr1.Line3,Addr1.City,Addr1.State,Addr1.Zip,Addr1.Country,Addr2.Type,Addr2.Line1,Addr2.Line2,Addr2.Line3,Addr2.City,Addr2.State,Addr2.Zip,Addr2.Country,Addr3.Type,Addr3.Line1,Addr3.Line2,Addr3.Line3,Addr3.City,Addr3.State,Addr3.Zip,Addr3.Country
My question might be related to below link
OpenCSV CSV to JavaBean
I didn't see that thread has a proper answer (I am not sure if I miss any from that thread)
Can we achieve same thing with any of the existing csv libraries such as supercsv, opencsv?
If I am using supercsv - can I map System.UniqueID column of csv to systemUniqueID property of my bean

You can certainly do this with Super CSV using CsvDozerBeanReader. See this example on the website.
It's also explained in a bit more detail on this SO answer.
You may also be interested in this recent question, as it demonstrates the different ways to achieve deep/indexed mapping with Super CSV (with and without using Dozer).
Following the CsvDozerBeanReader example on the website, to read the CSV from your question you would use a field mapping of:
final String[] fieldMapping = new String[]{
"uniqueId",
"name",
"selfRegEnabled",
"addrList[0].type",
"addrList[0].line1",
"addrList[0].line2",
"addrList[0].line3",
"addrList[0].city",
"addrList[0].state",
"addrList[0].zip",
"addrList[0].country",
"addrList[1].type",
"addrList[1].line1",
"addrList[1].line2",
"addrList[1].line3",
"addrList[1].city",
"addrList[1].state",
"addrList[1].zip",
"addrList[1].country",
"addrList[2].type",
"addrList[2].line1",
"addrList[2].line2",
"addrList[2].line3",
"addrList[2].city",
"addrList[2].state",
"addrList[2].zip",
"addrList[2].country"
};
Also, because the selfRegEnabled field is a boolean, you'll need to use cell processors to transform the String value into a Boolean - to do this you'd use the ParseBool processor.

Related

Update specific attributes with DynamoDBMapper in java

I want to update only the specific attributes of the item using DynamoDBMapper.
For example, I have a User table with attributes viz., id, name, address.
#Data
#DynamoDBTable(tableName = "Users")
public class User {
#DynamoDBHashKey
#DynamoDBGeneratedUuid(DynamoDBAutoGenerateStrategy.CREATE)
private String id;
#DynamoDBAttribute
private String name;
#DynamoDBAttribute
private Address address;
}
I want to update only the address attribute and not the other fields (selective update).
I could find a sample example by using UpdateItemSpec but couldn't find it for DynamoDBMapper.
With UpdateItemSpec, I can use withUpdateExpression() to define update expression.
More details can be found here.
Is there any way, to achieve the same with DynamoDBMapper?
Use the UPDATE_SKIP_NULL_ATTRIBUTES SaveBehavior
More details on: https://aws.amazon.com/blogs/developer/using-the-savebehavior-configuration-for-the-dynamodbmapper/
Add the SaveBehavior to your save operation and keep fields other than id and address null:
mapper.save(user, new DynamoDBMapperConfig(SaveBehavior.UPDATE_SKIP_NULL_ATTRIBUTES));

Single responsibility principle: method DoDatabaseBackup is doing a lot of things

I'm developing a C# library with .NET Framework 4.7 and Visual Studio 2017 Community.
I'm trying to understand and use single responsibility principle correctly.
I have this class to do a backup in a SQL Server 2012 Database:
public static class DbManagement
{
private static string sqlBackupStatement =
"BACKUP DATABASE [{0}] TO DISK = N'{1}' WITH COMPRESSION, COPY_ONLY, NAME=N'{2}'";
/// <summary>
/// Do backup for a database.
/// </summary>
/// <param name="connectionString">Connection's string to database</param>
/// <param name="path">Path to safe the database</param>
/// <param name="backupFileName">Backup's file name</param>
/// <param name="backupName">This name will be used to identify this backup.</param>
/// <returns>Database's execution result</returns>
public static int DoDatabaseBackup(
string connectionString,
string path,
string backupFileName,
string backupName)
{
if (string.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentNullException(nameof(path));
if (string.IsNullOrWhiteSpace(backupFileName))
throw new ArgumentNullException(nameof(backupFileName));
if (string.IsNullOrWhiteSpace(backupName))
throw new ArgumentNullException(nameof(backupName));
string databaseName = GetDatabaseName(connectionString);
string fullPath = GetFullPath(path);
string pathWithFile = fullPath + backupFileName + "_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".bak";
string description = string.Format("{0} - Full database Backup", backupName);
if (!Directory.Exists(fullPath))
Directory.CreateDirectory(fullPath);
string sqlStatement = string.Format(sqlBackupStatement, databaseName, pathWithFile, description);
TRZLDbContext context = new TRZLDbContext(connectionString);
return
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sqlStatement);
}
private static string GetDatabaseName(string connectionString)
{
SqlConnectionStringBuilder sqlConnBuilder =
new SqlConnectionStringBuilder(connectionString);
return sqlConnBuilder.InitialCatalog;
}
private static string GetFullPath(string path)
{
StringBuilder builder = new StringBuilder(path);
if (!path.EndsWith("\\"))
builder.Append("\\");
DateTime today = DateTime.Now;
builder.Append(today.Year.ToString());
builder.Append("\\");
builder.Append(today.Month.ToString());
builder.Append("\\");
return builder.ToString();
}
}
I think a do a lot of things in method DoDatabaseBackup:
Get database name.
Get full path to store backup file.
Get full path with backup's file name.
Create backup's description.
Create directory where I will store the backup if it doesn't exist.
Create the SQL statement to do the backup.
And finally... do the backup.
Am I using Single Responsibility Principle correctly here? It it is not, do I have to move points 1 to 6 to 6 methods?
You could refactor this into a number of separate classes with distinct responsibilities. If you think of the types of objects that could be represented here you would have something like:
A connection string
A database backup
A backup statement
A backup file name
With SRP it's important to think about how objects may change. For example, the algorithm for changing the backup file name may change, so that may want to be represented in a separate class so that it can be swapped out for a new algorithm if necessary. You may need to change the SQL statement if you start using a different type of database. The connection string also has a dependency on SQL which may change in future.
I had a go at refactoring your above method and came up with the following:
public class ConnectionString
{
private readonly string connectionString;
public ConnectionString(string connectionString)
{
this.connectionString = connectionString;
}
public string DatabaseName()
{
SqlConnectionStringBuilder sqlConnBuilder =
new SqlConnectionStringBuilder(this.connectionString);
return sqlConnBuilder.InitialCatalog;
}
}
public class BackupFileName
{
private readonly string backupFilePath;
private readonly string backupFileName;
public BackupFileName(string backupFilePath, string backupFileName)
{
this.backupFilePath = backupFilePath;
this.backupFileName = backupFileName;
}
public string FullPath => this.backupFilePath;
public override string ToString()
{
return this.GetFullPath(this.backupFilePath) + this.backupFileName + "_" +
DateTime.Now.ToString("yyyyMMddHHmm") + ".bak";
}
private string GetFullPath(string path)
{
StringBuilder builder = new StringBuilder(path);
if (!path.EndsWith("\\"))
builder.Append("\\");
DateTime today = DateTime.Now;
builder.Append(today.Year.ToString());
builder.Append("\\");
builder.Append(today.Month.ToString());
builder.Append("\\");
return builder.ToString();
}
}
public class BackupStatement
{
private string sqlBackupStatement =
"BACKUP DATABASE [{0}] TO DISK = N'{1}' WITH COMPRESSION, COPY_ONLY, NAME=N'{2}'";
private readonly string databaseName;
private readonly string filePath;
private readonly string description;
public BackupStatement(string databaseName, string filePath, string description)
{
this.databaseName = databaseName;
this.filePath = filePath;
this.description = description;
}
public override string ToString()
{
return string.Format(sqlBackupStatement, databaseName, filePath, description);
}
}
public class DatabaseBackup
{
private readonly ConnectionString connectionString;
private readonly string backupName;
private readonly BackupFileName backupFileName;
public DatabaseBackup(
string connectionString,
string path,
string backupFileName,
string backupName)
{
if (string.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException(nameof(connectionString));
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentNullException(nameof(path));
if (string.IsNullOrWhiteSpace(backupFileName))
throw new ArgumentNullException(nameof(backupFileName));
if (string.IsNullOrWhiteSpace(backupName))
throw new ArgumentNullException(nameof(backupName));
this.connectionString = new ConnectionString(connectionString);
this.backupFileName = new BackupFileName(path, backupFileName);
this.backupName = backupName;
}
/// <summary>
/// Creates a backup for a database.
/// </summary>
/// <returns>Database's execution result</returns>
public int Create()
{
string description = string.Format("{0} - Full database Backup", this.backupName);
if (!Directory.Exists(this.backupFileName.FullPath))
Directory.CreateDirectory(this.backupFileName.FullPath);
TRZLDbContext context = new TRZLDbContext(this.connectionString.ToString());
return
context.Database.ExecuteSqlCommand(
TransactionalBehavior.DoNotEnsureTransaction,
new BackupStatement(
this.connectionString.DatabaseName(),
this.backupFileName.ToString(),
description).ToString());
}
}
It's not perfect, and each of the above classes should really be using interfaces (as per Dependency Inversion) but I hope it illustrates a point.
Both.
Don't recreate things like the backup name on the fly. Have a method/function/whatever that gives that to you.
Otherwise, it is fine for a function to do more than one thing to accomplish a goal which subsumes those things. That said, don't duplicate actions found elsewhere (like building a backup path).
The single responsibility principle exists to modularize unique objects to single places -- it is a generalization of the One Definition Rule. (Yeah, I know you're using Java. Sorry...LOL)

key prefixes with documents in spring-data-couchbase repositories

I commonly use a prefix pattern when storing documents in couchbase. For example a user document might have a key like "user::myusername" and an order document might have a key of "order::1".
I'm new to spring-data and don't see a way to easily make it work with these prefixes. I can specify a field in my object like:
public class UserLogin {
public static final String dbPrefix = "user_login::";
#Id
private String id;
private String username;
.
.
.
public void setUsername(String username) {
this.username = username;
this.id = dbPrefix + this.username;
}
}
and have a Crud repository
public interface UserLoginRepo extends CrudRepository<UserLogin, String> {
}
This is an ok work around because I can:
...
userLoginRepo.save(login)
UserLogin login = userLoginRepo.findOne(UserLogin.dbPrefix + "someuser");
...
It would be really nice if there were some way to have the repository automatically use the prefix behind the scenes.
not sure if you are asking a question here. Spring-data doesn't have any built-in mechanism to do what you want. If you are using Spring-cache with couchbase this is possible since you can annotate your cached methods with naming patterns like this, for example, in spring cache you can do something like this on the persistence method:
#Cacheable(value = "myCache", key = "'user_login::'+#id")
public UserLogin getUserLogin()
Obviously though, this is Spring cache and not spring data, however both are supported in the same library.

signature get error on Alljoyn framework?

i'm working Android App use Alljoyn framework and i have some prolem
i have a custom object
public class Package implements BusObject {
public static enum DataSendType {
TEXT,IMAGE
}
public static enum PackageStatus {
NONE, SENDING, DONE
}
#Signature("s")
private String m_id;
#Signature("a")
private ArrayList<DataPackage> m_listPackage;
#Signature("r")
private PackageStatus m_status;
#Signature("r")
private DataSendType m_type;
#Signature("s")
private String m_packageName;
}
and interface
#BusInterface (name="xxxx.simpleinterface")
public interface SimpleInterface {
#BusSignal (name="Chat", signature="o")
public void Chat(Package message) throws BusException;
}
but i get this error cannot marshal class Package into 'o' when use Chat(Package)..
pls help me, because i can't get this error out for 2 weeks.
sorry because my English is too bad :)
looking at your code it looks like what you are trying to send is a struct the signature for a struct should be "r" or the actual signature surrounded by parenthesizes ( and ). i.e. for Package the signature would be "(sayiis)"
With AllJoyn you can send an array but not an ArrayList and you must specify the type of data that is in the array.
Since your DataSendType specified TEXT or IMAGE I made the assumption that you want to send an array of bytes.
Most of the items I did not add a signature to because AllJoyn can figure out the signature using reflection. AllJoyn however does not know that enums will be transmitted as integers so I did have to specify the signature for the enums.
Package did not have to implement BusObject. In your code when you implement your SimpleInterface that should extend the SimpleInterface and `BusObject'
Anything sent using AllJoyn should be public so the interface can read the member variables.
public class Package {
public static enum DataSendType{
TEXT,
IMAGE
}
public static enum PackageStatus {
NONE,
SENDING,
DONE
}
#Position(0)
public String m_id;
#Position(1)
public byte[] m_listPackage;
#Position(2)
#Signature("i")
public PackageStatus m_status;
#Position(3)
#Signature("i")
public DataSendType m_type;
#Position(4)
public String m_packageName;
}
for the interface the signature should be "r" for struct the signature "o" means object path. This is an AllJoyn object path which means it just a string with path data.
#BusInterface (name="xxxx.simpleinterface")
public interface SimpleInterface {
#BusSignal (name="Chat", signature="r")
public void Chat(Package message) throws BusException;
}
If you really need to use an ArrayList convert the ArrayList to an actual array before sending the Chat signal.

Collections in QueryDSL projections

I am trying to use a projection to pull in data from an entity an some relations it has. However. The constructor on the projection takes three arguments; a set, integer and another integer. This all works fine if I don't have the set in there as an argument, but as soon as I add the set, I start getting SQL syntax query errors.
Here is an example of what I'm working with...
#Entity
public class Resource {
private Long id;
private String name;
private String path;
#ManyToOne
#JoinColumn(name = "FK_RENDITION_ID")
private Rendition rendition;
}
#Entity
public class Document {
private Long id;
private Integer pageCount;
private String code;
}
#Entity
public class Rendition {
Long id;
#ManyToOne
#JoinColumn(name="FK_DOCUMENT_ID")
Document doc;
#OneToMany(mappedBy="rendition")
Set<Resource> resources;
}
public class Projection {
#QueryProjection
public Projection(Set<Resource> resources, Integer pageCount, String code) {
}
}
Here is the query like what I am using (not exactly the same as this is a simplified version of what I'm dealing with)....
QRendition rendition = QRendition.rendition;
Projection projection = from(rendition)
.where(rendition.document().id.eq(documentId)
.and(rendition.resources.isNotEmpty())
.limit(1)
.singleResult(
new QProjection(rendition.resources,
rendition.document().pageCount,
rendition.document().code));
This query works fine as long as my projection class does not have the rendition.resources in it. If I try and add that in, I start getting malformed SQL errors (it changes the output sql so that it starts with this.
select . as col_0_0_
So, I guess my main question here is how do I include a Set as an object in a projection? Is it possible, or am I just doing something wrong here?
Using collections in projections is unreliable in JPA. It is safer to join the collection and aggregate the results instead.
Querydsl can also be used for result aggregation http://www.querydsl.com/static/querydsl/3.2.0/reference/html/ch03s02.html#d0e1799
In your case something like this
QRendition rendition = QRendition.rendition;
Projection projection = from(rendition)
.innerJoin(rendition.document, document)
.innerJoin(rendition.resources, resource)
.where(document.id.eq(documentId))
.limit(1)
.transform(
groupBy(document.id).as(
new QProjection(set(resources),
document.pageCount,
document.code)));

Resources