Total Pageviews

2016/05/06

Using Project Lombok to eliminate boilerplate code

What is boilerplate code
Boilerplate is the term used to describe sections of code that have to be included in many places with little or no alteration. It is more often used when referring to languages which are considered verbose, i.e. the programmer must write a lot of code to do minimal jobs.

How-to
We can use @Data to generate getters for all fields:
Before:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package albert.practice.xstream.beans;

import java.io.Serializable;

public class Doc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 訂單編號
    private String regId;

    // 要保人ID
    private String ownerId;

    // 保單號碼
    private String policyNumber;

    // 被保人 ID
    private String insuredId;

    // 表單代碼
    private String formId;

    public String getRegId() {
        return regId;
    }

    public void setRegId(String regId) {
        this.regId = regId;
    }

    public String getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(String ownerId) {
        this.ownerId = ownerId;
    }

    public String getPolicyNumber() {
        return policyNumber;
    }

    public void setPolicyNumber(String policyNumber) {
        this.policyNumber = policyNumber;
    }

    public String getInsuredId() {
        return insuredId;
    }

    public void setInsuredId(String insuredId) {
        this.insuredId = insuredId;
    }

    public String getFormId() {
        return formId;
    }

    public void setFormId(String formId) {
        this.formId = formId;
    }

}

After using @Data:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package albert.practice.xstream.beans;

import java.io.Serializable;

import lombok.Data;

@Data
public class Doc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 訂單編號
    private String regId;

    // 要保人ID
    private String ownerId;

    // 保單號碼
    private String policyNumber;

    // 被保人 ID
    private String insuredId;

    // 表單代碼
    private String formId;

}


We can use @NoArgsConstructor to generate a no-args constructor.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package albert.practice.xstream.beans;

import java.io.Serializable;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class Doc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 訂單編號
    private String regId;

    // 要保人ID
    private String ownerId;

    // 保單號碼
    private String policyNumber;

    // 被保人 ID
    private String insuredId;

    // 表單代碼
    private String formId;

}

We can use @AllArgsConstructor to generate an all-args constructor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package albert.practice.xstream.beans;

import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Doc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 訂單編號
    private String regId;

    // 要保人ID
    private String ownerId;

    // 保單號碼
    private String policyNumber;

    // 被保人 ID
    private String insuredId;

    // 表單代碼
    private String formId;

}

We can use @ToString generate an implementation for the toString method inherited by all objects, consisting of printing the values of relevant fields. 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package albert.practice.xstream.beans;

import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Doc implements Serializable {

    private static final long serialVersionUID = 1L;

    // 訂單編號
    private String regId;

    // 要保人ID
    private String ownerId;

    // 保單號碼
    private String policyNumber;

    // 被保人 ID
    private String insuredId;

    // 表單代碼
    private String formId;

}

Reference
[1] http://jnb.ociweb.com/jnb/jnbJan2010.html
[2] https://en.wikipedia.org/wiki/Boilerplate_%28text%29

2016/05/05

[Apache Tika] How to Check File's Media Type?

Problem
We have a file upload function, we need to check the file media type is as expected. 
For example, if the file upload function only accept xls or xlsx file, other media type is disallowed.
How to do it?

How-to
Before cope with this problem, you need to add tika dependency in your pom.xml
1
2
3
4
5
6
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-core</artifactId>
            <version>1.9</version>
            <scope>compile</scope>
        </dependency>

Assume we will check some media types as bellows:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package albert.practice.file;

//media type list: http://www.iana.org/assignments/media-types/media-types.xhtml
public class MediaTypes {

 public static final String DOC = "application/msword";
 public static final String DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
 public static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
 public static final String TXT = "text/plain";
 public static final String JPG = "image/jpeg";
 public static final String PDF = "application/pdf";
 public static final String EXE = "application/x-msdownload";

}

Here is the approach to check file media type:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package albert.practice.file;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.tika.Tika;

/**
 * 
 * @author albert
 * 
 */
public class FileMediaTypeTest {

 // set up the path and name of test file
 private final String DROPBOX_HOME = "/Users/albert/Dropbox/";
 private final String DOC_FILE = DROPBOX_HOME + "庫務組/交付文件(第二階段)/PDS/NTA_PSR_FMS_PDS_1030930_V1.0.doc";
 private final String DOCX_FILE = DROPBOX_HOME + "債務管理系統/NTA_IFMIS_DBM_測試及操作文件/DBM001E.docx";
 private final String XLSX_FILE = DROPBOX_HOME
   + "庫務組/交付文件(第二階段)/PDS/NTA_PSR_FMS_PDS_附件/NTA_PSR_FMS_PDS_1030901_需求追溯表.xlsx";
 private final String TXT_FILE = DROPBOX_HOME + "庫務組/測試.txt";
 private final String JPG_FILE = DROPBOX_HOME + "庫務組/ads100fa.jpg";
 private final String PDF_FILE = DROPBOX_HOME + "eBooks/Head First Python.pdf";
 private final String FAKE_EXE_FILE = DROPBOX_HOME + "eBooks/The Intelligent Investor 拷貝.exe";

 public static void main(String[] args) throws IOException {
  new FileMediaTypeTest().testFileMediaType();
 }

 public void testFileMediaType() throws IOException {
  checkFileMediaType(DOC_FILE, MediaTypes.DOC);
  checkFileMediaType(DOCX_FILE, MediaTypes.DOCX);
  checkFileMediaType(XLSX_FILE, MediaTypes.XLSX);
  checkFileMediaType(TXT_FILE, MediaTypes.TXT);
  checkFileMediaType(JPG_FILE, MediaTypes.JPG);
  checkFileMediaType(PDF_FILE, MediaTypes.PDF);
  checkFileMediaType(FAKE_EXE_FILE, MediaTypes.EXE);
 }

 public void checkFileMediaType(String sourceFile, String expectedMediaType) throws IOException {

  File file = FileUtils.getFile(sourceFile);
  try {
   Tika tika = new Tika();

   // Detects the media type of the given file. The type detection is
   // based on the document content and a potential known file
   // extension.
   String mediaType = tika.detect(file);

   System.out.println("\nchecking " + sourceFile + "...");

   if (!(expectedMediaType.equals(mediaType))) {
    String actualMediaTypeName = mediaType;
    String errorMsg = "Wrong media type ! Expected:" + expectedMediaType + ", Actual:"
      + actualMediaTypeName;
    System.err.println(errorMsg);
    throw new RuntimeException(errorMsg);
   } else {
    System.out.println("Correct media type : " + mediaType);
   }

  } catch (IOException e) {
   e.printStackTrace();
  }
 }

}

Console looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
checking /Users/albert/Dropbox/庫務組/交付文件(第二階段)/PDS/NTA_PSR_FMS_PDS_1030930_V1.0.doc...
Correct media type : application/msword

checking /Users/albert/Dropbox/債務管理系統/NTA_IFMIS_DBM_測試及操作文件/DBM001E.docx...
Correct media type : application/vnd.openxmlformats-officedocument.wordprocessingml.document

checking /Users/albert/Dropbox/庫務組/交付文件(第二階段)/PDS/NTA_PSR_FMS_PDS_附件/NTA_PSR_FMS_PDS_1030901_需求追溯表.xlsx...
Correct media type : application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

checking /Users/albert/Dropbox/庫務組/測試.txt...
Correct media type : text/plain

checking /Users/albert/Dropbox/庫務組/ads100fa.jpg...
Correct media type : image/jpeg

checking /Users/albert/Dropbox/eBooks/Head First Python.pdf...
Correct media type : application/pdf

checking /Users/albert/Dropbox/eBooks/The Intelligent Investor 拷貝.exe...
Wrong media type ! Expected:application/x-msdownload, Actual:image/png
Exception in thread "main" java.lang.RuntimeException: Wrong media type ! Expected:application/x-msdownload, Actual:image/png
 at albert.practice.file.FileMediaTypeTest.checkFileMediaType(FileMediaTypeTest.java:59)
 at albert.practice.file.FileMediaTypeTest.testFileMediaType(FileMediaTypeTest.java:38)
 at albert.practice.file.FileMediaTypeTest.main(FileMediaTypeTest.java:28)


Reference
[1] https://tika.apache.org/
[2] http://www.iana.org/assignments/media-types/media-types.xhtml

2016/05/04

[XStream] How to create XML via XStream (a more complex example)

Requirement
The XSD for xml is as following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Attributes">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="WorkLoad"/>
              <xs:element type="xs:string" name="DetailDocCat"/>
              <xs:element type="xs:string" name="ScanDate"/>
              <xs:element type="xs:time" name="ScanTime"/>
              <xs:element type="xs:float" name="StockingNumber"/>
              <xs:element type="xs:string" name="CaseId"/>
              <xs:element name="PolicyNumbers">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="PolicyNumber" maxOccurs="unbounded" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="ProposalNums">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="ProposalNum" maxOccurs="unbounded" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The resulting XML looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<Root>
  <Attributes>
    <WorkLoad>TW_NEWNBED</WorkLoad>
    <DetailDocCat>xxx要保書</DetailDocCat>
    <ScanDate>2016/03/02</ScanDate>
    <ScanTime>15:56:00</ScanTime>
    <StockingNumber>2016E000001</StockingNumber>
    <CaseId>ABCD-201600100001</CaseId>
    <PolicyNumbers>
      <PolicyNumber>A12345678</PolicyNumber>
    </PolicyNumbers>
    <ProposalNums>
      <ProposalNum>B87654321</ProposalNum>
    </ProposalNums>
  </Attributes>
</Root>


How-to
Step1. According xsd definition, creating classes to be serialized

Root class looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package albert.practice.xstream.beans;

import java.io.Serializable;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class Root implements Serializable {

 private static final long serialVersionUID = 1L;

 private Attributes Attributes;

 public Attributes getAttributes() {
  return Attributes;
 }

 public void setAttributes(Attributes Attributes) {
  this.Attributes = Attributes;
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


Attributes class looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class Attributes implements Serializable {

 private static final long serialVersionUID = 1L;

 private String WorkLoad;

 private String DetailDocCat;

 private String ScanDate;

 private String ScanTime;

 private String StockingNumber;

 private String CaseId;

 private List<PolicyNumbers> PolicyNumbers;

 private List<ProposalNums> ProposalNums;

 public String getWorkLoad() {
  return WorkLoad;
 }

 public void setWorkLoad(String WorkLoad) {
  this.WorkLoad = WorkLoad;
 }

 public String getDetailDocCat() {
  return DetailDocCat;
 }

 public void setDetailDocCat(String DetailDocCat) {
  this.DetailDocCat = DetailDocCat;
 }

 public String getStockingNumber() {
  return StockingNumber;
 }

 public void setStockingNumber(String StockingNumber) {
  this.StockingNumber = StockingNumber;
 }

 public List<PolicyNumbers> getPolicyNumbers() {
  return PolicyNumbers;
 }

 public void setPolicyNumbers(List<PolicyNumbers> policyNumbers) {
  PolicyNumbers = policyNumbers;
 }

 public String getCaseId() {
  return CaseId;
 }

 public void setCaseId(String CaseId) {
  this.CaseId = CaseId;
 }

 public String getScanDate() {
  return ScanDate;
 }

 public void setScanDate(String ScanDate) {
  this.ScanDate = ScanDate;
 }

 public String getScanTime() {
  return ScanTime;
 }

 public void setScanTime(String ScanTime) {
  this.ScanTime = ScanTime;
 }

 public List<ProposalNums> getProposalNums() {
  return ProposalNums;
 }

 public void setProposalNums(List<ProposalNums> proposalNums) {
  ProposalNums = proposalNums;
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


PolicyNumbers looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class PolicyNumbers implements Serializable {

 private static final long serialVersionUID = 1L;

 private String PolicyNumber;
 private List<PolicyNumbers> PolicyNumberList;

 public List<PolicyNumbers> getPolicyNumberList() {
  return PolicyNumberList;
 }

 public void setPolicyNumberList(List<PolicyNumbers> policyNumberList) {
  PolicyNumberList = policyNumberList;
 }

 public PolicyNumbers(String policyNumber) {
  this.PolicyNumber = policyNumber;
 }

 public String getPolicyNumber() {
  return PolicyNumber;
 }

 public void setPolicyNumber(String policyNumber) {
  this.PolicyNumber = policyNumber;
 }

 public PolicyNumbers() {
  super();
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


ProposalNumbers looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class ProposalNums implements Serializable {

 private static final long serialVersionUID = 1L;

 private String ProposalNum;
 private List<ProposalNums> ProposalNumList;

 public String getProposalNum() {
  return ProposalNum;
 }

 public void setProposalNum(String proposalNum) {
  ProposalNum = proposalNum;
 }

 public List<ProposalNums> getProposalNumList() {
  return ProposalNumList;
 }

 public void setProposalNumList(List<ProposalNums> proposalNumList) {
  ProposalNumList = proposalNumList;
 }

 public ProposalNums(String proposalNum) {
  super();
  ProposalNum = proposalNum;
 }

 public ProposalNums() {
  super();
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }

}


Step2. Utilize XStream API to fulfill our requirement
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class XStreamTestClient {

 public static void main(String[] args) throws IOException {

  // create an instance of beans and populate its fields:
  Attributes attribute = new Attributes();
  attribute.setWorkLoad("TW_NEWNBED");
  attribute.setDetailDocCat("xxx要保書");
  attribute.setScanDate("2016/03/02");
  attribute.setScanTime("15:56:00");
  attribute.setStockingNumber("2016E000001");
  attribute.setCaseId("ABCD-201600100001");

  List<PolicyNumbers> policyNumberList = new ArrayList<PolicyNumbers>();
  policyNumberList.add(new PolicyNumbers("A12345678"));

  attribute.setPolicyNumbers(policyNumberList);

  List<ProposalNums> proposalNumList = new ArrayList<ProposalNums>();
  proposalNumList.add(new ProposalNums("B87654321"));

  attribute.setProposalNums(proposalNumList);

  Root root = new Root();
  root.setAttributes(attribute);

  String xml = new XStreamTestClient().toXml(root);
  System.out.println(xml);

 }

 public String toXml(Root root) {
  // instantiate the XStream class
  XStream xStream = new XStream();

  // create an alias to the desired class:
  xStream.alias("Root", Root.class);
  xStream.alias("PolicyNumbers", PolicyNumbers.class);
  xStream.alias("ProposalNums", ProposalNums.class);

  // whenever you have a collection which doesn't need to display it's
  // root tag, you can map it as an implicit collection
  xStream.addImplicitCollection(Attributes.class, "PolicyNumbers");
  xStream.addImplicitCollection(Attributes.class, "ProposalNums");

  return xStream.toXML(root);
 }
}