2013年7月6日 星期六

dbunit初體驗 - 從現有XML DATA中過濾出需要的資料

之前使用的QueryDataSet可以下SQL Query來SELECT出想要的資料(請見此篇),
然而QueryDataSet好像只能接受從connection資料來建立...這不符合我的需求,找到一個好方法,就是使用RowFilterTable 搭配IRowFilter,直接來看code:


 public static ITable filterXmlDataCol(
   String xmlDataFile, String tableName,IDatabaseConnection conn
   , final String expectColNames[] , final Object expectColVals[]) throws Exception {
  
  IDataSet databaseDataSet = getDataSetFromXmlFile(xmlDataFile);
  ITable actualTable = databaseDataSet.getTable(tableName);
  
  IRowFilter rowFilter = new IRowFilter() {
   @Override
   public boolean accept(IRowValueProvider rowValueProvider) {
    try {
     for(int i=0 ; i< expectColNames.length ; ++i){
      Object columnValue = rowValueProvider.getColumnValue(expectColNames[i]);
      if (!columnValue.equals(expectColVals[i]))
       return false;
     }
     return true;
    } catch (DataSetException ex) {
     ex.printStackTrace();
    }
    return false;
   }
  };
  RowFilterTable filteredRowsTable = new RowFilterTable(
    actualTable, rowFilter);
  return filteredRowsTable;
 }

使用方式:
現有XML DATA:


  
  
    

    
    
    
    

我只希望以XMLDATA建立出的ITable有條件:product == "17公司" and name=="tables"的資料,那麼就照以下方式呼叫:
   ITable expect = DBUnitUtilities.filterXmlDataCol("datasheet\\FactoryInfo.xml","FactoryInfo"
     , _dbunitConnection,new String[]{"name","product"},new String[]{"17公司","tales"} );


這樣就可以過濾囉~~

debug一下其實可以發現RowFilterTable並不是真的將資料給"過濾"掉了,只是將原先的Table給wrap後,然後帶入自行建立的IRowFilter(上述line 8~23),並在每一次巡迴column資料時以自定義的@ovverride accept()回傳true(資料保留) 或 false(資料移除)
回傳true的row index就會被保留在filteredRowIndexes這個List中囉。


p.s:
星期一就要交差幾乎會開天窗的我居然還在研究test.....只希望我這個堅持是對的....畢竟我真的不想再寫垃圾Code穩定度又差又無法擴充又不敢修改的爛東西了阿.........0rz...


參考:Filtering data sets and comparing results using DBUnit

2013年7月3日 星期三

android - 新增Activity在與原先不同的package時,出現R cannot be resolved to a variable 錯誤...

參考:Android: Including multiple Java Packages to Manifest

假設我有兩個Activity,分別在不同的package:
1.com.ex.package1.PActivity1
2.com.ex.package2.PActivity2

該怎麼做才能將上述錯誤消除呢?

修改AndroidManifest.xml

   
  
//....


    
 
    

首先注意的是:

  1.  <manifest> 中的package屬性,必須指定到兩個分歧package的上一層
  2. 每一個<activity>中的android:name屬性,都必須以 . 起始之後再跟者分歧的package name
  3. 在每一個Activity上加入 import com.ex.R;
重新clean rebuild後應該可以消除error了

2013年6月30日 星期日

TinyXml、TinyXPath 基本讀取


需求:欲讀取下列XML檔案中的TEXT資料:
 

 127.0.0.1
 800


 
string readXmlSingleText(string file,string xpath){

 char errStr[MSG_MIN_LEN] = {'\0'};

 TiXmlDocument xmlDoc(file.c_str());
 xmlDoc.LoadFile();

 if(xmlDoc.ErrorId() > 0){
              //error do something..
 }

 TiXmlElement* pRootElement = xmlDoc.RootElement();

 if(!pRootElement){
             //error do something..
 }


 TinyXPath::xpath_processor xproc(pRootElement,xpath.c_str()); 
 unsigned  nodeCount =xproc.u_compute_xpath_node_set();          
 if(nodeCount==0) {
            //error do something..
 } 

 TiXmlNode *xnode = xproc.XNp_get_xpath_node(0);
 return string(xnode->ToElement()->GetText());
}

使用方式如下:
    string ip = readXmlSingleText("setting.xml","//ROOT/SEND-IP");

2013年6月28日 星期五

SQL - 如何指定DATE PART的特定時間

假設我有一個需求,需要在TSQL中宣告一個時間,日期為當下的日期(例如現在撰文的6/29)、並指定DATEPART HOUR為20,DATEPART MIN為45,該如何做?


 
     DECLARE @STARTDATE AS DATETIME 
     SET @STARTDATE = GETDATE();
     SET @STARTDATE =  DATEADD(hour, 20, DATEDIFF(DAY, 0, GETDATE()))
     SET @STARTDATE =  DATEADD(minute , 45, @STARTDATE)

其中最重要的應該是第2行
SET @STARTDATE = DATEADD(hour, 20, DATEDIFF(DAY, 0, GETDATE())),
先運用DATEDIFF(DAY, 0, GETDATE())找出,當下時間(假設為2013/6/29 18:05)與第0天(1900-1-1)相差了幾"日",此時取出來的時間皆為00:00分;之後再運用DATEADD指定hour與欲得到的hour就可以了

2013年6月23日 星期日

google checkout API -only for US and UK

這篇只是抱怨文

因為工作需要研究了google in-app billing機制,但是研究了之後發現這個機制其實對於開發者來說並不安全,因為檢查購買資訊判斷這些都是由CLIENT端發動,然後由CLIENT做驗證(驗證購買資訊),以 Android SDK中的in-app Billing範例TrivialDrive來說,【infinite gas】、【premium】這兩樣等於是無敵VIP的物品是否購買的判斷,居然都是從CLIENT端透過API發動詢問,然後從CLIENT端接收回應,由CLIENT開發者自行決定是否有購買...這怎麼看都是個大問題,找了關於in-app Billing Server Side validate方面的討論挺多的,結果找到了Google CheckOut的API,頓時眼睛一亮,這就是我要的!!

接著照者說明開始做...奇怪了...找的到merchant ID,就是找不到merchant Key啊!!繼續google下去,才發現原來要註冊為正式的checkout商家會員,居然只限定US and UK(請看某使用者回應)...@&*^#&# ,因為英文閱讀能力不好,所以這樣找尋大概來來回回花了3小時以上有吧.........得到最後的答案是這樣真的很.........


所以答案是,google in-app billing機制不合我用,可是還是看到不少game使用,神X之塔是因為這樣才被改的無限寶石是吧??但RO手機版也有使用,卻沒有這種問題的樣子,還是他們有美國據點或關係才能使用呢? 這就不得而知了..

好吧其實嚴格來說這篇也不算是完全抱怨啦,至少我知道了他們機制only for US and UK...

更新:
這裡 給了我希望,這做法應該是可行的!!怎麼我就沒想到呢,來去試試看...


2013/6/27 update:
忘記更新,確定可行,因為buy的時候不需要key,所以key可以安全地置放於server端驗證使用~








2013年6月22日 星期六

android初體驗 - 利用SharedPreferences來保存暫時資料


先貼Code,以下為goole in-app billing的Example擷取出來:

  
    void saveData() {
        SharedPreferences.Editor spe = getPreferences(MODE_PRIVATE).edit();
        spe.putInt("tank", mTank);
        spe.commit();
        Log.d(TAG, "Saved data: tank = " + String.valueOf(mTank));
    }

讀取回資料的方式也相當簡單:
  
    void loadData() {
        SharedPreferences sp = getPreferences(MODE_PRIVATE);
        mTank = sp.getInt("tank", 2);
        Log.d(TAG, "Loaded data: tank = " + String.valueOf(mTank));
    }

上述的getPreferences(int mode)其實等同於呼叫getSharedPreferences(activity's class name, int mode)
而SharedPreferences.getInt(String key, int defValue) 後的第二個參數代表是default value
應該可以很簡單理解所以就先記錄下來吧!

2013年6月21日 星期五

dbunit初體驗 - 新增table data from existing xml data


首先,做一些setup工作
        
private MsSqlConnection _dbunitConnection;
 @Before
 public void setUp() throws Exception {
     _dbunitConnection = new MsSqlConnection(DBUnitUtilities.createHsqlDBConnection(), null);
      //do something setup..
 }

重點在這:
 IDataSet setup = DBUnitUtilities.getDataSet("datasheet\\Banner11.xml");
 DatabaseOperation.CLEAN_INSERT.execute(_dbunitConnection,setup);