Total Pageviews

2017/11/02

[Java] MessageFormat

Problem
How to takes a set of objects, formats them, then inserts the formatted strings into the pattern at the appropriate places.

Example 1.



Example 2.



How-To

Here has an example to demonstrate how to do message format:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package albert.practice.stringFormat;

import java.text.Format;
import java.text.MessageFormat;

public class StringFormatExample {
    
    public String getFormattedMessage(String message, String... values) {
       Format messageFormat = new MessageFormat(message);
       return messageFormat.format(values);
    }
    
}


Test case is as bellows:
 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
package albert.practice.stringFormat;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class StringFormatExampleTest {

    private StringFormatExample stringFormat;
    private String unformatedMessage = "";
    private String phone = "";
    private String otp;
    private String anotherUnformatedMessage;
    private String error;
    
    @Before
    public void setup() {
        stringFormat = new StringFormatExample();
        unformatedMessage = "驗證碼傳送成功。手機號碼: {0}, 簡訊內容:驗證碼為:{1}";
        anotherUnformatedMessage = "驗證碼傳送失敗,失敗原因:{1}。手機號碼: {0}";
        phone = "0910123456";
        otp = "12345";
        error = "HTTP Server is down";
    }
    
    @Test
    public void testReturnWith1000Separator() {
        String str = stringFormat.returnWith1000Separator(1234567890);
        log.debug(str);
        assertEquals("1,234,567,890", str);
    }
    
    @Test
    public void testGetFormattedMessage() {
        String formatedMsg = stringFormat.getFormattedMessage(unformatedMessage, phone, otp);
        log.debug("formatedMsg = " + formatedMsg);
        assertEquals("驗證碼傳送成功。手機號碼: 0910123456, 簡訊內容:驗證碼為:12345", formatedMsg);
        
        String anotherFormatedMsg = stringFormat.getFormattedMessage(anotherUnformatedMessage, phone, error);
        log.debug("anotherFormatedMsg = " + anotherFormatedMsg);
        assertEquals("驗證碼傳送失敗,失敗原因:HTTP Server is down。手機號碼: 0910123456", anotherFormatedMsg);
    }

}
 

print logs:
1
2
14:57:18.679 [main] DEBUG a.p.s.s - formatedMsg = 驗證碼傳送成功。手機號碼: 0910123456, 簡訊內容:驗證碼為:12345
14:57:18.679 [main] DEBUG a.p.s.s - anotherFormatedMsg = 驗證碼傳送失敗,失敗原因:HTTP Server is down。手機號碼: 0910123456 



2017/11/01

[閱讀筆記] Common Stocks and Uncommon Profits (3/4)


  1. 既然是保守投資者,又要挑選出成長股,這兩者邏輯是否牴觸?其實不然,當考量到通膨的影響時,你就會理解成長型的公司的重要性。面對腳步越來越快的世界,公司不可能站在原地不動,一家公司不是成長就是萎縮,強大的攻擊力就是最好的防禦力。一家無法往上走的公司,無可避免地只會往下走下坡
  2. 保守/謹慎投資的第二個象限:第一象限強調的是公司對於生產、行銷、研發與財務的能力,第二象限強調是公司在生產、行銷、研發與財務部門是否有稱職的人選,朝向公司的目標前進
  3. 若一家大公司,需要從公司外部找人來擔任該公司的CEO,而不是從內部拔擢,這肯定是個壞兆頭。無論現在的財報多漂亮,其代表公司內部出了一些問題
  4. 若一家公司的薪資結構是,排名第一名的比第二名、第三名的人多非常多,這就是一個警訊。代表其薪資差異是劇烈的往下掉,而非緩和下降,這也同時告訴你,主要的錢都給了最高主管,底下的員工沒有得到該有的報酬
  5. 一家公司是否適合保守投資與長期持有的三個條件
    1. 公司必須體認到這個世界的運作不斷在變化,且速度越來越快:若只沉浸在過去成功的紀錄,以為過去的作法在未來依樣有效,這家公司只會走下坡
    2. 公司必須善待每個階層的員工:包含創造良好與氣氛融洽工作環境、正面的處理員工的抱怨、讓優秀員工得到財務上的獎勵與公司的認可等。將員工視為重要資產的公司,對於長期投資的投資人來說,是非常重要的因素
    3. 有遠見的公司,不會急著在每個會計期間結束時,產生最漂亮的盈餘數據,真正的成長導向的公司不會這麼做:成長導向的公司會聚焦在賺的錢要足夠能投入研發企業的新產品、新流程。今天花在研發的每一塊錢,在未來可能會賺到好幾塊錢
  6. 真實的投資成長目標不僅僅只是賺錢,而是避免損失
  7. 保守/謹慎投資的第三個象限:
    1. 公司有沒有它可以做,但是別人做得沒有他好的產品或服務?
    2. 其是否能夠長期維持高於業界平均的獲利能力?
  8. 高於業界平均的獲利能力,對於投資者非常重要。但是該如何維持高於平均的獲利能力?擁有專利保護是一種方式,另外一種是讓現有或潛在對手沒有任何誘因,不想進入此領域,也是一種方式
  9. 所謂的高於業界平均的利潤,指的是大約比第二名的競爭者高2~3%左右,會是一個好的狀況,當其利潤高過其他競爭者太多,反而會引誘其他競爭者進入
  10. 若公司要維持長久的高獲利,期必須要滿足兩個要件:
    1. 公司所銷售的產品或服務必須建立起高品質與可靠度的聲譽
    2. 公司所銷售的產品或服務對象,要是眾多的小客戶,而非少數的大客戶
  11. 當泡沫出現時,你無法預估他會持續多久後才破滅,有可能持續幾年,也有可能只出現幾個月
  12. 對於一個保守謹慎的投資人,若投資標的符合前三個象限,且本益比也很低的話,這是一個最安全的標的
  13. 本益比 (price-earnings ratio) 並不是從真實發生的事情所產生的,其是從金融圈 (financial community) 目前所深信的事情所產生。不要單靠本益比來作為買賣的決定因素,因為本益比並非客觀的數據
  14. 利率是影響股市的最重要的因素,若利率走高,資金會從股市匯出,導致股市走低;若利入走低,資金會流入股市,推升股價
  15. 一個好的企業需具備兩個基本的特性
    1. 有能力規劃長期的計畫,而不是總是著眼於每日例行事務上的績效提升
    2. 當犯下重大錯誤時,必須清楚認清所犯下的錯誤,並採取補救措施,記取教訓
  16. 一家值得投資的公司,其不只要擁有強大的銷售團隊來銷售公司產品,還要能密切觀察持續變動的需求,以及客戶想要什麼
  17. 聰明與愚笨的主要差別在,聰明的人會從錯誤中學習到教訓,愚笨的人則是一直重複犯錯
  18. 公司由上到下的人員素質很重要,尤其這兩項
    1. 企業能力 (business ability):此能力包含基層員工每日例行執行事項是否有優於業界的工作效率與品質,高階主管是否有規劃長遠的計畫能力,維持長期成長動能
    2. 經營者的是否正派 / 正直 (decency):不正派 / 正直的經營者,只會想到自己的利益,不會理會股東們的利益,也不會擁有熱情且有忠誠度的工作團隊
  19. Shakespeare曾說過:人生潮起潮落,若能把握機會乘風破浪,必能馬到成功。若不能把握機會,人生的航行就只能受限於悲苦之中。我們漂流在茫茫大海中,當浪潮來時,我們必須把握住機會;若否,則會使我們的冒險失敗。投資不嘗試如此嗎?
  20. 當根據前述的原則挑選的股票,請至少持有三年,三年期滿再根據其績效來決定是要繼續持有還是賣出
  21. 如果發現一檔好的且價格合理的股票,不要為了要以10元、10.25元或10.5元買進而躊躇 (battling for “eighths and qiarters”)。當你沒有買到,在股票一飛衝天之後,你才會發現你犯了昂貴的錯誤
  22. 不要晉升一個不曾犯過錯誤的人,因為這種人從來沒做過什麼事情
  23. 如果你無法做得比別人好,不如不要做
  24. 不要去投資你不熟悉的產業,你要知道你能力的限制
  25. 如果一家公司的未來前景是正面的,即便已知在不久的將來會從目前高點下跌,我會建議繼續持有而非賣出。一家好的公司,會再爬起來並超越過去的高點
  26. 如果投資的標的是一個財務穩健的且管理良好的公司,即便是遇到猛烈的熊市,也不會抹除其持有的價值。我的建議是,請忽略短期的波動
  27. 短期的價格波動是非常難以預測的,我不相信頻繁的殺進殺出的遊戲 (in and out game) 可以讓你賺到可觀的利潤


2017/10/31

2017/10 Travel

淡水
DSC02376

DSC02402

DSC02404

DSC02380



2017/10/11

[CSS] Font Size Problem in iOS

Problem
I am testing my web page in every browser (ex. Chrome, Firefox, IE, Safari, etc.), iOS and Android. Each platform is working fine except iOS. 

The problem is the font size of the text in specific table cell is larger than other.


How-To
Add the following code in my CSS file is working:
body {
    -webkit-text-size-adjust: 100%;
}


Reference
[1] https://stackoverflow.com/questions/2545542/font-size-rendering-inconsistencies-on-an-iphone

2017/10/10

How do I Keep Leading Zeros in CSV Files?

Problem
I am using Java to write data into CSV file. 
One of the column in the CSV file is cell phone number.
If I open this CSV file by Microsoft Excel, the first digit will disappear.

Take the first record for example. The correct value is 0912123456, but it show 912123456 in Microsoft Excel.

How-To
When you write cell number into CSV file, you should write ="0912123456" instead of 0912123456.



2017/10/09

[AngularJS] How to resize text width on demand ?

Problem
I am using AngularJS to implement web application. 

You can find an URL text filed in the web page. 

The requirement is the width of the URL text field will resize based on the text length which key in by end user. 

How to do it?


How-To
You can make good use of ng-keyup and ng-style to fulfill this requirement.
Using ng-keyup to calculate the length of text and using ng-style to set width at the same time.

The HTML code snippet looks like:
1
2
3
4
5
6
7
8
    <div class="row">
      <div class="form-group col-sm-3">
       <!- ignore -->        
        <label for="url" class="control-label label-width-5">URL</label> 
        <input type="text" id="url" name="url" class="form-control" data-ng-model="model.url" 
               data-ng-keyup="keyInUrl()" data-ng-style="{'width':urlWidth}">
      </div>
    </div>


The JavaScript code snippet are the following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
  // set the initial value for url width
  $scope.urlWidth = 200;    

  // calculate width at runtime
  $scope.keyInUrl = function() {
   var url = $scope.model.url;
   if (!isEmptyOrUndefined($scope.model.url)){
    var width = ((url.length + 1) * 9);
       console.log('width = ' + width);
       if(width > 200) {
        $scope.urlWidth = width;
       } else  {
        $scope.urlWidth = 200;
       }
   }
  }


Demo:


2017/10/08

[Oracle to SQL Server Migration] NVL

Problem
In Oracle, NVL function lets you replace null (returned as a blank) with a string in the results of a query. 




If expr1 is null, then NVL returns expr2. If expr1 is not null, then NVL returns expr1.

The SQL statement is as follows:
SELECT DRAWING_ID,
       NVL(TARGET_INSFEE, 0)
FROM CAM_DRAWING

Owing to NVL is only for Oracle, but it cannot be executed in Microsoft SQL Server.


How-To
You can use ISNULL instead of NVL in Microsoft SQL Server.
The SQL statement is as bellows:
SELECT DRAWING_ID,
       ISNULL(TARGET_INSFEE, 0)
FROM CAM_DRAWING



2017/10/07

Using JPA to Insert and Retrieve BLOBs

Problem
I am using JPA to do CRUD in persistence tier. If I would like to insert an image file into Microsoft SQL Server, how to do it?

The table schema is the following:
CREATE TABLE "CAM_CAMPAIGN_IMGS"
(
   CAMPAIGN_ID nvarchar(10) NOT NULL,
   CID nvarchar(100) NOT NULL,
   IMAGE varbinary(MAX) NOT NULL,
   CONTENT_TYPE nvarchar(100) NOT NULL,
   CONSTRAINT PK_CAM_CAMPAIGN_IMGS PRIMARY KEY (CAMPAIGN_ID, CID)
)
GO


How-To
You can see image column add @Lob annotation in entity class:
package com.xxx.ecp.commons.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Table;


@Entity
@Table(name="CAM_CAMPAIGN_IMGS")
public class CamCampaignImg implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private CamCampaignImgPK id;

    @Column(name="CONTENT_TYPE")
    private String contentType;

    @Lob
    @Column(name="IMAGE")
    private byte[] image;

    public CamCampaignImg() {
    }

    public CamCampaignImgPK getId() {
        return this.id;
    }

    public void setId(CamCampaignImgPK id) {
        this.id = id;
    }

    public String getContentType() {
        return this.contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public byte[] getImage() {
        return this.image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }

}


Code snippet regarding insert image file looks like:
     CamCampaignImgPK imgPK = new CamCampaignImgPK();
     imgPK.setCampaignId(camCampaign.getCampaignId());
     imgPK.setCid(form.getImgFileName());
     
     CamCampaignImg camCampaignImg = new CamCampaignImg();
     camCampaignImg.setId(imgPK);
     camCampaignImg.setContentType(form.getContentType());
     
     // convert to bytes from input stream
     camCampaignImg.setImage(form.getImgFile().getBytes());
     
     camCampaiganImgRep.create(camCampaignImg);


Code snippet about retrieve image file looks like:
     List<CamCampaignImg> imgs = camCampaignImgRepCust.findByCampaignId(campaign.getCampaignId());
     for(CamCampaignImg img : imgs) {
        // get image's content type
        String contentType = img.getContentType();
        // get image file's input stream
        InputStream imgInputStream = new ByteArrayInputStream(img.getImage());
     }


2017/10/06

How to prevent JavaScript cache in Chrome during development ?

Problem
I am working on a web application project, and using Google Chrome as my browser to do development and test.

I face a JavaScript cache problem during my development, the JavaScript file which I updated does not take effect. It's very annoying, how do I do?


How-To
Open "incognito window" (無痕視窗) can overcome this annoying problem. In incognito mode (無痕模式), you will retrieve up-to-date JavaScript file after page reloaded.


2017/10/05

How to check file's media type?

Problem
If I have a file upload function in my web application, this function need to check the file which upload by user is image file or not. How to do it?

How-To
You can make good use of Apache Tika to fulfill this requirement.

Add dependency in your pom.xml
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-core</artifactId>
            <version>1.14</version>
            <scope>compile</scope>
        </dependency>




Sample code is as follow:
package albert.practice.file;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

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

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FileContentTypeUtils {

    private static List<String> imageMediaTypes = new ArrayList<>();

    private static void setImageMediaTypes() {
        // http://www.fileformat.info/info/mimetype/image/index.htm
        imageMediaTypes = Arrays.asList("image/cgm", "image/fits",
                "image/g3fax", "image/gif", "image/ief", "image/jp2",
                "image/jpeg", "image/jpm", "image/jpx", "image/naplps",
                "image/png", "image/prs.btif", "image/prs.pti", "image/t38",
                "image/tiff", "image/tiff-fx", "image/vnd.adobe.photoshop",
                "image/vnd.cns.inf2", "image/vnd.djvu", "image/vnd.dwg",
                "image/vnd.dxf", "image/vnd.fastbidsheet", "image/vnd.fpx",
                "image/vnd.fst", "image/vnd.fujixerox.edmics-mmr",
                "image/vnd.fujixerox.edmics-rlc",
                "image/vnd.globalgraphics.pgb", "image/vnd.microsoft.icon",
                "image/vnd.mix", "image/vnd.ms-modi", "image/vnd.net-fpx",
                "image/vnd.sealed.png", "image/vnd.sealedmedia.softseal.gif",
                "image/vnd.sealedmedia.softseal.jpg", "image/vnd.svf",
                "image/vnd.wap.wbmp", "image/vnd.xiff");
    }

    public static Boolean isImage(String sourceFile) throws IOException {
        setImageMediaTypes();
        Boolean isImage = Boolean.FALSE;
        File file = FileUtils.getFile(sourceFile);
        Tika tika = new Tika();
        try {
            String mediaType = tika.detect(file);
            isImage = imageMediaTypes.contains(mediaType);
        } catch (IOException e) {
            throw e;
        }
        return isImage;
    }

}



Test code is the following:
package albert.practice.file;

import java.io.IOException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class FileContentTypeUtilsTest extends FileContentTypeUtils {

    private String imageFile;
    private String pdfFile;

    @Before
    public void setup() {
        imageFile = "/Users/albert/Dropbox/picture/panda.png";
        pdfFile = "/Users/albert/Dropbox/test_測試.pdf";
    }

    @Test
    public void testImageFile() throws IOException {
        Assert.assertTrue(isImage(imageFile));
    }

    @Test
    public void testPdfFile() throws IOException {
        Assert.assertFalse(isImage(pdfFile));
    }

}



Test results are shown bellow:






2017/10/04

How to Improve Code Coverage in Enumeration Type ?

Problem
Assume I have a enumeration as bellows:
package albert.practice.designPattern.factory;

public enum ShapeEnum {
    CIRCLE, RECTANGLE, SQUARE, TRIANGLE, OVAL;
}


After I run code coverage test, the coverage rate in enumeration is low:


How to improve its code coverage rate?




How-To
To get rid of this issue, you need to call the values() methods in this enumeration. You can check the testShapeEnum() in the test code:
package albert.practice.designPattern.factory;

import static org.junit.Assert.assertEquals;

import java.util.function.Supplier;

import org.junit.Test;

public class ShapeFactoryTest {

    @Test
    public void testDifferentShape() {
        Supplier<ShapeFactory> shapeFactory = ShapeFactory::new;
        shapeFactory.get().getShape(ShapeEnum.CIRCLE).draw();
        shapeFactory.get().getShape(ShapeEnum.RECTANGLE).draw();
        shapeFactory.get().getShape(ShapeEnum.OVAL).draw();
        shapeFactory.get().getShape(ShapeEnum.SQUARE).draw();
        shapeFactory.get().getShape(ShapeEnum.TRIANGLE).draw();
    }

    @Test
    // https://stackoverflow.com/questions/4512358/emma-coverage-on-enum-types/4548912#4548912
    public void testShapeEnum() {
        ShapeEnum[] shapeEnums = ShapeEnum.values();
        assertEquals(5, shapeEnums.length);
    }

}







2017/10/03

[閱讀筆記] 惡魔財經辭典 (The Devil’s Financial Dictionary) [6/6]


  1. 如果是做多,虧損不可能高過百分百(除非是用融資保證金);如果是做空(short sale),虧損可能無上限,因為資產價格可能不跌反漲,而且可以無限制上漲。做空的風險:賣掉不屬於自己的東西,要不就得買回來,要不就得進監獄
  2. 投資操作要以徹底分析為基礎,確保本金安全無虞,還要有令人滿意的報酬率。不符合這些要求的操作就是投機(speculation)
  3. 所謂投機(speculation),通常是什麼東西當紅就買什麼,然後希望找到願意接手的傻瓜
  4. 每一個買對股票的挑股者(stock picker),背後一定有一個賣錯股票的挑股者;一個經理人的收益,必定是另一個經理人的虧損
  5. Stop-loss order(停損單)是指當有價證券跌到某個價格以下時提交賣出指令,但在實務操作是,也可能反倒停掉收益
  6. Tactic (戰術)是短期的決策,目的是為了落實長期的 strategy (策略)。但是在華爾街,strategy 通常是委婉的說法,其實是指快速、頻繁交易的 tactic
  7. 根據技術分析,support (支撐)是指資產的價格接近過去低點。技術分析師認為,價格接近 support level (支撐水準)時,絕對不可能繼續下跌,至少短期不會。但是,有智慧的投資人都知道,不論是哪種金融資產,支撐價位只有一個:0
  8. 塑造未來期待的時候,投資人應該先確定自己對過去歷史的理解沒有失真或扭曲。雖說史書是由勝利者寫的,但歷史是由勝利者與失敗者共同製造的
  9. Tax shelter (避稅)是一種複雜的投資,這種投資可能保護投資者的收入不受高額稅負危害,但卻必然會暴露於高額佣金之下
  10. 股票和其他有價證券的未來價格,是由標的的資產產生的現金流決定,而不是由證券本身的過去價格決定的。這就好像,一個球隊未來的比賽紀錄是由隊員的表現決定的,而不是由他們過去的得分決定的
  11. 在華爾街,有這樣一條很實用的通則:行話越是難懂,他描述的東西就越不可能賺錢
  12. Trailer (佣金) 是付給經紀人的一筆年費,因為他賣了共同基金或其他投資商品給你。你買一次基金,你的經紀人就會拿到 trailer ,通常是 0.25% 到 1%,只要你持有這隻基金就要付這筆錢,就算你沒有獲得任何關於這隻基金的任何「建議」
  13. 市場價格持續不斷波動中,很多證券商會鼓勵客戶去找出趨勢,並根據趨勢來進行交易。但趨勢(trend)很難持久,試圖從中獲利的業餘投資人也很少能持久
  14. 承銷(underwrite)是指投資銀行承擔股票和債券的銷售工作,他們先向發行銀行買進股票或債券,然後再立即轉賣給投資大眾,該銀行通常會收取高達收益的 7%,以補償自己持有那幾個小時所承擔的風險
  15. 宇宙(universe)常用來比喻一大堆投資可能標的或組合,分析師或投資經理人可以經理人可以從中隨意挑選組合。這個宏偉的字眼掩蓋了一個事實:對於無數的專業投資人來說,universe 包含的是一個極為狹隘的參考框架,以及極為有限的購買選擇
  16. 價格(price)是你所支付的,價值(value)是你得到的
  17. 神智清楚的買家在取得所有必要資訊後進行評估(根據該資產未來可能賺多少錢來評估),得出該項資產到底值多少錢,這就是所謂的「價值」。一支股票的價值取決於該公司產生現金的潛力,不會每季、每月、每日產生改變。股票價格在短短一天內就會改變成千上萬次,這只會造成股票交易者產生某些反應,卻完全不會影響該公司的生意
  18. 對一家公司未來盈餘的洞察力或信心,通常只能透過後照鏡來看
  19. Visibility 是 predictability 的同義字,但其實也是 self-illusion (自我欺騙)的同義字。從來沒有人能看到一點未來;未來一直都是 invisible
  20. 一直在賺錢時,持有人會說他們對波動性(volatility)感到自在,但一旦開始虧錢,就會說他們討厭波動性。該筆投資並沒有改變,改變的只是他們的觀感。金融市場波動最大的元素,就是投資人對波動的看法
  21. 追求投資效益率的過程中,損失的金錢比被人拿槍指著搶劫失去的金錢還多