[Groovy] 配列および個数指定による組み合わせ結果の列挙

 Groovy  [Groovy] 配列および個数指定による組み合わせ結果の列挙 はコメントを受け付けていません。
5月 262012
 

■環境
Groovy Version: 1.8.6 JVM: 1.7.0_02 Vendor: Oracle Corporation OS: Windows 7

■combination.groovy


def combination(List list, int n) {
  if (n == 1) return list.collect{[it]}
  
  def rList = []
  (list.size()-1).times { int i ->
    rList += combination(list[i+1..-1], n-1).collect{[list[i]]+it}
  }
  return rList
}


Object a = "a"
Object b = ["list"]
Object c = 3
Object d = 1.0
Object e = false
Object f = ["key":"value"]
Object g = new BigDecimal("100")

def list5 = [a, b, c, d, e]
assert combination(list5, 0) == []
assert combination(list5, 1) == [[a], [b], [c], [d], [e]]
assert combination(list5, 2) == [[a, b], [a, c], [a, d], [a, e],
                                 [b, c], [b, d], [b, e],
                                 [c, d], [c, e],
                                 [d, e]]
assert combination(list5, 3) == [[a, b, c], [a, b, d], [a, b, e],
                                 [a, c, d], [a, c, e], [a, d, e],
                                 [b, c, d], [b, c, e], [b, d, e],
                                 [c, d, e]]
assert combination(list5, 4) == [[a, b, c, d], [a, b, c, e],
                                 [a, b, d, e], [a, c, d, e],
                                 [b, c, d, e]]
assert combination(list5, 5) == [[a, b, c, d, e]]
assert combination(list5, 6) == []
assert list5 == [a, b, c, d, e]

def list6b = [a, b, c, d, e, a]
def list6B = list6b.unique(false)
assert combination(list6B, 0) == []
assert combination(list6B, 1) == [[a], [b], [c], [d], [e]]
assert combination(list6B, 2) == [[a, b], [a, c], [a, d], [a, e],
                                  [b, c], [b, d], [b, e],
                                  [c, d], [c, e],
                                  [d, e]]
assert combination(list6B, 3) == [[a, b, c], [a, b, d], [a, b, e],
                                  [a, c, d], [a, c, e], [a, d, e],
                                  [b, c, d], [b, c, e], [b, d, e],
                                  [c, d, e]]
assert combination(list6B, 4) == [[a, b, c, d], [a, b, c, e],
                                  [a, b, d, e], [a, c, d, e],
                                  [b, c, d, e]]
assert combination(list6B, 5) == [[a, b, c, d, e]]
assert combination(list6B, 6) == []
assert list6b == [a, b, c, d, e, a]

def list6C = [a, b, c, d, e, a]
assert combination(list6C, 0) == []
assert combination(list6C, 1) == [[a], [b], [c], [d], [e], [a]]
assert combination(list6C, 2) == [[a, b], [a, c], [a, d], [a, e], [a, a],
                                  [b, c], [b, d], [b, e], [b, a],
                                  [c, d], [c, e], [c, a],
                                  [d, e], [d, a],
                                  [e, a]]
assert combination(list6C, 3) == [[a, b, c], [a, b, d], [a, b, e], [a, b, a],
                                  [a, c, d], [a, c, e], [a, c, a], [a, d, e],
                                  [a, d, a], [a, e, a],
                                  [b, c, d], [b, c, e], [b, c, a], [b, d, e],
                                  [b, d, a], [b, e, a],
                                  [c, d, e], [c, d, a], [c, e, a],
                                  [d, e, a]]
assert combination(list6C, 4) == [[a, b, c, d], [a, b, c, e], [a, b, c, a],
                                  [a, b, d, e], [a, b, d, a], [a, b, e, a],
                                  [a, c, d, e], [a, c, d, a], [a, c, e, a],
                                  [a, d, e, a],
                                  [b, c, d, e], [b, c, d, a], [b, c, e, a],
                                  [b, d, e, a],
                                  [c, d, e, a]]
assert combination(list6C, 5) == [[a, b, c, d, e], [a, b, c, d, a], [a, b, c, e, a],
                                  [a, b, d, e, a], [a, c, d, e, a], [b, c, d, e, a]]
assert combination(list6C, 6) == [[a, b, c, d, e, a]]
assert combination(list6C, 7) == []
assert list6C == [a, b, c, d, e, a]

def list6 = [a, b, c, d, e, f]
assert combination(list6, 0) == []
assert combination(list6, 1) == [[a], [b], [c], [d], [e], [f]]
assert combination(list6, 2) == [[a, b], [a, c], [a, d], [a, e], [a, f],
                                 [b, c], [b, d], [b, e], [b, f],
                                 [c, d], [c, e], [c, f],
                                 [d, e], [d, f],
                                 [e, f]]
assert combination(list6, 3) == [[a, b, c], [a, b, d], [a, b, e], [a, b, f],
                                 [a, c, d], [a, c, e], [a, c, f], [a, d, e],
                                 [a, d, f], [a, e, f],
                                 [b, c, d], [b, c, e], [b, c, f], [b, d, e],
                                 [b, d, f], [b, e, f],
                                 [c, d, e], [c, d, f], [c, e, f],
                                 [d, e, f]]
assert combination(list6, 4) == [[a, b, c, d], [a, b, c, e], [a, b, c, f],
                                 [a, b, d, e], [a, b, d, f], [a, b, e, f],
                                 [a, c, d, e], [a, c, d, f], [a, c, e, f],
                                 [a, d, e, f],
                                 [b, c, d, e], [b, c, d, f], [b, c, e, f],
                                 [b, d, e, f],
                                 [c, d, e, f]]
assert combination(list6, 5) == [[a, b, c, d, e], [a, b, c, d, f], [a, b, c, e, f],
                                 [a, b, d, e, f], [a, c, d, e, f], [b, c, d, e, f]]
assert combination(list6, 6) == [[a, b, c, d, e, f]]
assert combination(list6, 7) == []
assert list6 == [a, b, c, d, e, f]

def list7 = [a, b, c, d, e, f, g]
assert combination(list7, 0) == []
assert combination(list7, 1) == [[a], [b], [c], [d], [e], [f], [g]]
assert combination(list7, 2) == [[a, b], [a, c], [a, d], [a, e], [a, f], [a, g],
                                 [b, c], [b, d], [b, e], [b, f], [b, g],
                                 [c, d], [c, e], [c, f], [c, g],
                                 [d, e], [d, f], [d, g],
                                 [e, f], [e, g],
                                 [f, g]]
assert combination(list7, 3) == [[a, b, c], [a, b, d], [a, b, e], [a, b, f],
                                 [a, b, g], [a, c, d], [a, c, e], [a, c, f],
                                 [a, c, g], [a, d, e], [a, d, f], [a, d, g],
                                 [a, e, f], [a, e, g], [a, f, g],
                                 [b, c, d], [b, c, e], [b, c, f], [b, c, g],
                                 [b, d, e], [b, d, f], [b, d, g], [b, e, f],
                                 [b, e, g], [b, f, g],
                                 [c, d, e], [c, d, f], [c, d, g], [c, e, f],
                                 [c, e, g], [c, f, g],
                                 [d, e, f], [d, e, g], [d, f, g],
                                 [e, f, g]]
assert combination(list7, 4) == [[a, b, c, d], [a, b, c, e], [a, b, c, f],
                                 [a, b, c, g], [a, b, d, e], [a, b, d, f],
                                 [a, b, d, g], [a, b, e, f], [a, b, e, g],
                                 [a, b, f, g], [a, c, d, e], [a, c, d, f],
                                 [a, c, d, g], [a, c, e, f], [a, c, e, g],
                                 [a, c, f, g], [a, d, e, f], [a, d, e, g],
                                 [a, d, f, g], [a, e, f, g],
                                 [b, c, d, e], [b, c, d, f], [b, c, d, g],
                                 [b, c, e, f], [b, c, e, g], [b, c, f, g],
                                 [b, d, e, f], [b, d, e, g], [b, d, f, g],
                                 [b, e, f, g],
                                 [c, d, e, f], [c, d, e, g], [c, d, f, g],
                                 [c, e, f, g],
                                 [d, e, f, g]]
assert combination(list7, 5) == [[a, b, c, d, e], [a, b, c, d, f], [a, b, c, d, g],
                                 [a, b, c, e, f], [a, b, c, e, g], [a, b, c, f, g],
                                 [a, b, d, e, f], [a, b, d, e, g], [a, b, d, f, g],
                                 [a, b, e, f, g], [a, c, d, e, f], [a, c, d, e, g],
                                 [a, c, d, f, g], [a, c, e, f, g], [a, d, e, f, g],
                                 [b, c, d, e, f], [b, c, d, e, g], [b, c, d, f, g],
                                 [b, c, e, f, g], [b, d, e, f, g],
                                 [c, d, e, f, g]]
assert combination(list7, 6) == [[a, b, c, d, e, f], [a, b, c, d, e, g],
                                 [a, b, c, d, f, g], [a, b, c, e, f, g],
                                 [a, b, d, e, f, g], [a, c, d, e, f, g],
                                 [b, c, d, e, f, g]]
assert combination(list7, 7) == [[a, b, c, d, e, f, g]]
assert combination(list7, 8 ) == []
assert list7 == [a, b, c, d, e, f, g]


def list0 = []
assert combination(list0, 0) == []
assert combination(list0, 1) == []
assert combination(list0, 2) == []
assert list0 == []

def list1 = [a]
assert combination(list1, 0) == []
assert combination(list1, 1) == [[a]]
assert combination(list1, 2) == []
assert list1 == [a]

def list2 = [a, b]
assert combination(list2, 0) == []
assert combination(list2, 1) == [[a], [b]]
assert combination(list2, 2) == [[a, b]]
assert combination(list2, 3) == []
assert list2 == [a, b]

def list3 = [a, b, c]
assert combination(list3, 0) == []
assert combination(list3, 1) == [[a], [b], [c]]
assert combination(list3, 2) == [[a, b], [a, c],
                                 [b, c]]
assert combination(list3, 3) == [[a, b, c]]
assert combination(list3, 4) == []
assert list3 == [a, b, c]

def list4 = [a, b, c, d]
assert combination(list4, 0) == []
assert combination(list4, 1) == [[a], [b], [c], [d]]
assert combination(list4, 2) == [[a, b], [a, c], [a, d],
                                 [b, c], [b, d],
                                 [c, d]]
assert combination(list4, 3) == [[a, b, c], [a, b, d], [a, c, d],
                                 [b, c, d]]
assert combination(list4, 4) == [[a, b, c, d]]
assert combination(list4, 5) == []
assert list4 == [a, b, c, d]

/*
// 試行錯誤の残骸 orz..

def combination(List list, int n) {
  // def listP = new ArrayList(list)
  def listP = list.unique(false)
  def rList = []
  if (n == 1) return listP.collect{[it]}
  while (listP.size() > 0) {
    def head = listP.remove(0)
    combination(listP, n-1).each{ rList << [head]+it }
  }
  return rList
}

// 試行錯誤の残骸 orz.

def combination(List listIn, int n){
    // 非破壊的に"重複削除したList"を生成しセット
    List list = listIn.unique(false)
    List rList = []
    while(n>0 && list.size()>0){
        def temp = combinationPart([], [], new ArrayList(list), n)
        def object = list.remove(0)
        temp.findAll{ it?.getAt(0) == object }.each { rList << it }
        if(list.size()<n) break
    }
    return rList
}

private def combinationPart(List rList, List listTemp, List listIn, int n){
    def combinationPartInner = { List rListParam, List listInParam, int num ->
        while(listInParam.size()>0){
            combinationPart([], [], new ArrayList(listInParam), num)
                .each{ rListParam << it }
            listInParam.remove(0)
            if(num==1) break
        }
        return rListParam
    }

    if ( listIn.size() >= n ) {
        listTemp << listIn.remove(0)
        if ( listTemp.size() == n ) {
            if (!rList.contains(listTemp)){
                if (rList?.size()==0 || listTemp?.size()==1) {
                    rList << listTemp
                }
                if (rList?.size()>0 && listTemp?.size()>1){
                    if ( rList?.getAt(0)?.getAt(0) == listTemp?.getAt(0)) {
                        rList << listTemp
                    }
                }
            }
            listTemp =  new ArrayList(listTemp)
            listTemp.remove(0)
        } else if (n!=1) {
            combinationPartInner([], listIn, n-1).each {
                rList << ( new ArrayList(listTemp) + it )
            }
        }
        rList = combinationPart(rList, listTemp, listIn, n)
    }
    return rList
}
*/

[Groovy] iTunesからエクスポートしたLibrary XML (ライブラリ.xml)のパース

 Groovy  [Groovy] iTunesからエクスポートしたLibrary XML (ライブラリ.xml)のパース はコメントを受け付けていません。
2月 062012
 

■参考
XMLPropertyListConfiguration (Commons Configuration 1.9-SNAPSHOT API)
http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.html
—————————————————————
Property list file (plist) in XML format as used by Mac OS X (http://www.apple.com/DTDs/PropertyList-1.0.dtd).
This configuration doesn’t support the binary format used in OS X 10.4.
—————————————————————
  ↓↓↓↓↓↓
真・plist形式のxml読み込み用digester-rules(およびクラス) – terazzoの日記
http://d.hatena.ne.jp/terazzo/20080524/1211656594

■環境(STS)
JDK Compiler compliance level : 1.7
Groovy Compiler version 1.8.4.xx-20120118-1100-e37-M1
Maven Embedded (3.0.2/1.0.100.20110804-1717)
—————————————————————


  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-digester3</artifactId>
      <version>3.2</version>
    </dependency>
  </dependencies>

—————————————————————

■サンプルメインクラス(sample.Main.groovy)および実行結果


package sample

import parser.PlayList;
import parser.Track;
import parser.iTunesLibraryXMLParser;

def parser = new iTunesLibraryXMLParser("ライブラリ.xml")

PlayList playList = parser.getPlayList("ミュージック")
Map<Integer, Track> playlistItems = playList?.getPlaylistItems()

def artistList = []
for(Track track: playlistItems?.values()){
  artistList << track.getArtist()
}

def rankMap = [:]
artistList.each {
  rankMap.put(it, (rankMap.containsKey(it)?rankMap.get(it):0) +1)
}
rankMap.sort{it.value}.reverseEach {key, value ->
  println "$key : ${value}曲"
}

安室奈美恵 : 16曲
宇多田ヒカル : 15曲
RADWIMPS : 15曲
RIP SLYME : 14曲
矢井田瞳 : 13曲
YUKI : 12曲
福山雅治 : 10曲
大塚愛 : 9曲
いきものがかり : 9曲
絢香 : 8曲
ケツメイシ : 8曲
YUI : 7曲
Hilcrhyme : 7曲
 ・
 ・
 ・

■parser.utils.PropertyListUtils.groovy


package parser.utils

import java.io.IOException;
import java.net.URL;
import java.text.DateFormat
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
import org.xml.sax.SAXException;

/**
 * plist-rule.xmlを使ったDigesterによってライブラリXMLを読み込むクラス
 */
public class PropertyListUtils  {
  /**
   * plist-rule.xmlから作成したRulesModule
   */
  class MyRulesModule extends FromXmlRulesModule {
    URL ruleXml = getClass().getClassLoader().getResource("parser/utils/plist-rule.xml");

    @Override
    protected void loadRules() {
      loadXMLRules(ruleXml);
    }
  }

  /**
   * ライブラリXMLファイル読み込み用のDigester
   */
  private static Digester digester =
  DigesterLoader.newLoader( new PropertyListUtils.MyRulesModule() ).newDigester();

  /**
   * 指定したurlの内容をplistとして読み込み、内部の情報を戻す。
   * 内部のタグについて、arrayはjava.util.Listに、dictはjava.util.Mapに、
   * string, integer, dateはそれぞれString, Integer, java.util.Dateに変換する。
   * @param url XML形式のplistファイルを示すURL
   * @return plistの中身を戻す
   */
  public static Map load(URL url) throws IOException, SAXException {
    return (Map)((PropertyList) digester.parse(url)).getContent();
  }
  /**
   * 指定したurlの内容をplistとして読み込み、内部の情報を戻す。
   * 内部のタグについて、arrayはjava.util.Listに、dictはjava.util.Mapに、
   * string, integer, dateはそれぞれString, Integer, java.util.Dateに変換する。
   * @param file XML形式のplistファイルを示すFile
   * @return plistの中身を戻す
   */
  public static Map load(File file) throws IOException, SAXException {
    return (Map)((PropertyList) digester.parse(file)).getContent();
  }
}

/**
 * digesterでタグを処理する際に一時的に値を保持するラッパーインタフェース
 * @author terazzo
 */
interface ValueWrapper {
  /** @return 内部に保持する値を戻す */
  Object getValue();
}

/**
 * ValueWrapperを受け取りValueWrapperの内部の値を取得するクラス
 * @author terazzo
 */
abstract class Peeler {
  /**
   * valueを追加する
   * @param value 追加する値
   */
  public abstract void add(Object value);
  /**
   * wrapperの代わりにwrapperが内部に保持する値を取り出して追加する
   * @param wrapper 追加する値を含むValueWrapper
   */
  public void add(ValueWrapper wrapper) {
    add(wrapper.getValue());
  }
}

/**
 * plistタグを読み込む為のラッパークラス
 * @author terazzo
 */
class PropertyList extends Peeler {
  /** 内部ではObjectで保持*/
  private Object content;
  /**
   * 値を設定する
   * @param value plistタグ内の値(Map/List/String/Integerなど)
   */
  public void add(Object value) {
    this.content = value;
  }
  /** @return 内部に保持する値を戻す */
  public Object getContent() {
    return this.content;
  }
}

/**
 * arrayタグを読み込む為のラッパークラス
 * @author terazzo
 */
class Array extends Peeler implements ValueWrapper {
  /** 内部ではListで保持*/
  private List list = new ArrayList();

  /**
   * valueをlistに追加する
   * @param value 追加する値
   */
  public void add(Object value) {
    this.list.add(value);
  }
  /** @return 内部に保持するList値を戻す */
  public Object getValue() {
    return this.list;
  }
}

/**
 * dateタグを読み込む為のラッパークラス
 */
class Date implements ValueWrapper {
  /** 日付フォーマット(ISO 8601。実際は"yyyy-MM-dd'T'HH:mm:ss'Z'"で固定)。 */
  private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

  /** 内部的に保持する日付オブジェクト*/
  private java.util.Date date = null;

  /**
   * 文字列dateStringを日付として設定する
   * @param dateString 日付を表す文字列(フォーマットは"yyyy-MM-dd'T'HH:mm:ss'Z'")
   */
  public void takeDateString(String dateString) throws ParseException {
    DateFormat df = new SimpleDateFormat(DATE_FORMAT);
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    this.date = df.parse(dateString);
  }
  /** @return 内部に保持するDate値を戻す */
  public Object getValue() {
    return this.date;
  }
}

/**
 * dictタグを読み込む為のラッパークラス
 * @author terazzo
 */
class Dict extends Peeler implements ValueWrapper {
  /** 内部ではMapで保持*/
  private Map map = new HashMap();

  /** 最後に出現したkeyタグの値を保持 */
  private String key;

  /**
   * keyを設定する。この直後にaddした値をこのkeyを用いて内部のMapに追加する
   * @param key key文字列
   */
  public void setKey(String key) {
    this.key = key;
  }
  /**
   * valueをmapに追加する。最後に設定したkey値をキーとして使用する
   * @param value 追加する値
   */
  public void add(Object value) {
    this.map.put(this.key, value);
  }
  /** @return 内部に保持するMap値を戻す */
  public Object getValue() {
    return this.map;
  }
}

/**
* trueタグを読み込む為のラッパークラス
*/
class True implements ValueWrapper {
   /** @return 内部に保持するBoolean値を戻す */
   public Object getValue() {
     return Boolean.TRUE;
   }
}

/**
* falseタグを読み込む為のラッパークラス
*/
class False implements ValueWrapper {
   /** @return 内部に保持するBoolean値を戻す */
   public Object getValue() {
     return Boolean.FALSE;
   }
}

■parser.utils.plist-rule.xml


<?xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE digester-rules PUBLIC
  "-//Apache Commons //DTD digester-rules XML V1.0//EN"
  "http://commons.apache.org/digester/dtds/digester-rules-3.0.dtd">
  
<digester-rules>
    <object-create-rule pattern="plist" classname="parser.utils.PropertyList"/>
    <pattern value="*/key">
        <call-method-rule methodname="setKey" paramcount="1" paramtypes="java.lang.String"/>
        <call-param-rule paramnumber='0'/>
    </pattern>
    <pattern value="*/string">
        <call-method-rule methodname="add" paramcount="1" paramtypes="java.lang.String"/>
        <call-param-rule paramnumber='0'/>
    </pattern>
    <pattern value="*/integer">
        <call-method-rule methodname="add" paramcount="1" paramtypes="java.lang.Integer"/>
        <call-param-rule paramnumber='0'/>
    </pattern>
    <pattern value="*/true">
        <object-create-rule classname="parser.utils.True"/>
        <call-method-rule targetoffset="1" methodname="add" paramcount="1"
            paramtypes="parser.utils.ValueWrapper"/>
        <call-param-rule paramnumber='0'  from-stack="true"/>
    </pattern>
    <pattern value="*/false">
        <object-create-rule classname="parser.utils.False"/>
        <call-method-rule targetoffset="1" methodname="add" paramcount="1"
            paramtypes="parser.utils.ValueWrapper"/>
        <call-param-rule paramnumber='0'  from-stack="true"/>
    </pattern>
    <pattern value="*/date">
        <object-create-rule classname="parser.utils.Date"/>
        <call-method-rule targetoffset="1" methodname="add" paramcount="1"
            paramtypes="parser.utils.ValueWrapper"/>
        <call-param-rule paramnumber='0' from-stack="true"/>
        <call-method-rule targetoffset="0" methodname="takeDateString" paramcount="1" paramtypes="java.lang.String"/>
        <call-param-rule paramnumber='0'/>
    </pattern>
    <pattern value="*/dict">
        <object-create-rule classname="parser.utils.Dict"/>
        <call-method-rule targetoffset="1" methodname="add" paramcount="1" 
             paramtypes="parser.utils.ValueWrapper"/>
        <call-param-rule paramnumber='0'  from-stack="true"/>
    </pattern>
    <pattern value="*/array">
        <object-create-rule classname="parser.utils.Array"/>
        <call-method-rule targetoffset="1" methodname="add" paramcount="1" 
             paramtypes="parser.utils.ValueWrapper"/>
        <call-param-rule paramnumber='0'  from-stack="true"/>
    </pattern>
</digester-rules>

■parser.iTunesLibraryXMLParser.groovy


package parser

import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Map;

import org.xml.sax.SAXException;
import parser.utils.PropertyListUtils;

public class iTunesLibraryXMLParser {
  private static final String MAJOR_VERSION = "Major Version"
  private static final String MINOR_VERSION = "Minor Version"
  private static final String DATA = "Date"
  private static final String APPLICATION_VERSION = "Application Version"
  private static final String FEATURES = "Features"
  private static final String MUSIC_FOLDER = "Music Folder"
  private static final String LIBRARY_PERSISTENT_ID = "Library Persistent ID"
  private static final String TRACKS = "Tracks"
  private static final String PLAYLISTS = "Playlists"

  private Map content;

  iTunesLibraryXMLParser(String libraryXmlPath) throws IOException, SAXException{
    content = PropertyListUtils.load( new File(libraryXmlPath) );
    replaceTracks(content)
    replacePlaylists(content)
  }

  private def getIntegerValue = { Map map, String key -> (Integer) (map.get(key)) }
  private def getDateValue = { Map map, String key -> (Date) map.get(key) }
  private def getStringValue = { Map map, String key -> (String) map.get(key) }
  private def getBooleanValue = { Map map, String key -> (Boolean) map.get(key) }

  Integer getMajorVersion() {
    return getIntegerValue(content, MAJOR_VERSION)
  }
  Integer getMinorVersion() {
    return getIntegerValue(content, MINOR_VERSION)
  }
  Date getDate() {
    return getDateValue(content, DATA)
  }
  String getApplicationVersion() {
    return getStringValue(content, APPLICATION_VERSION)
  }
  Integer getFeatures() {
    return getIntegerValue(content, FEATURES)
  }
  String getMusicFolder() {
    return getStringValue(content, MUSIC_FOLDER)
  }
  String getLibraryPersistentID() {
    return getStringValue(content, LIBRARY_PERSISTENT_ID)
  }

  Map<Integer, Track> getTracks() {
    return (Map<Integer, Track>)content.get(TRACKS)
  }
  Map<String, PlayList> getPlayLists() {
    return (Map<String, PlayList>)content.get(PLAYLISTS)
  }
  PlayList getPlayList(String name) {
    return (PlayList)getPlayLists().get(name)
  }

  private def replaceTracks(Map content) {
    Map<String, Map> defTracks = (Map<String, Map>)content.get(TRACKS)
    Map<Integer, Track> newTracks = new HashMap<Integer, Track>()

    for (Map track : defTracks.values()) {
      def trackObj = new Track(track)
      newTracks.put(trackObj.getTrackID(), trackObj)
    }
    content.put(TRACKS, newTracks)
  }

  private def replacePlaylists(Map content) {
    List<Map> defPlaylists = (ArrayList<Map>)content.get(PLAYLISTS)
    Map<String, PlayList> newPlayLists = new LinkedHashMap<String, PlayList>()
    Map<Integer, Track> tracks = (Map<Integer, Track>)content.get(TRACKS)

    for(Map playlist : defPlaylists) {
      def playlistObj = new PlayList(playlist, tracks)
      newPlayLists.put(playlistObj.getName(), playlistObj)
    }
    content.put(PLAYLISTS, newPlayLists)
  }
}

■parser.PlayList.groovy


package parser

class PlayList {
  PlayList() {
  }
  PlayList(Map playlist, Map<Integer, Track> tracks) {
    def getIntegerValue = { String key -> (Integer) (playlist?.get(key)) }
    def getDateValue = { String key -> (Date) playlist?.get(key) }
    def getStringValue = { String key -> (String) playlist?.get(key) }
    def getBooleanValue = { String key -> (Boolean) playlist?.get(key) }

    setName(getStringValue("Name"))
    setMaster(getBooleanValue("Master"))
    setPlaylistID(getIntegerValue("Playlist ID"))
    setPlaylistPersistentID(getStringValue("Playlist Persistent ID"))
    setDistinguishedKind(getIntegerValue("Distinguished Kind"))
    setMusic(getBooleanValue("Music"))
    setMovies(getBooleanValue("Movies"))
    setAudiobooks(getBooleanValue("Audiobooks"))
    setBooks(getBooleanValue("Books"))
    setPurchasedMusic(getBooleanValue("Purchased Music"))
    setVisible(getBooleanValue("Visible"))
    setAllItems(getBooleanValue("All Items"))
    List<Map> playlistItems = (ArrayList<Map>)playlist?.get("Playlist Items")
    for(Map playlistItem : playlistItems) {
      Integer trackID = (Integer) (playlistItem?.get("Track ID"))
      getPlaylistItems().put(trackID, tracks?.get(trackID))
    }
  }

  /** Name */
  String name
  /** Master */
  Boolean master
  /** Playlist ID */
  Integer playlistID
  /** Playlist Persistent ID */
  String playlistPersistentID
  /** Distinguished Kind */
  Integer distinguishedKind
  /** Music */
  Boolean music
  /** Movies */
  Boolean movies
  /** Audiobooks */
  Boolean audiobooks
  /** Books */
  Boolean books
  /** Purchased Music */
  Boolean purchasedMusic
  /** Visible */
  Boolean visible
  /** All Items */
  Boolean allItems
  /** Playlist Items <Track ID, Track Object> */
  Map<Integer, Track> playlistItems = new LinkedHashMap<Integer, Track>()
}

■parser.Track.groovy


package parser

class Track {
  Track(){
  }

  Track(Map track){
    def getIntegerValue = { String key -> (Integer) (track?.get(key)) }
    def getDateValue = { String key -> (Date) track?.get(key) }
    def getStringValue = { String key -> (String) track?.get(key) }
    def getBooleanValue = { String key -> (Boolean) track?.get(key) }

    setTrackID(getIntegerValue("Track ID"))
    setName(getStringValue("Name"))
    setArtist(getStringValue("Artist"))
    setComposer(getStringValue("Composer"))
    setAlbum(getStringValue("Album"))
    setAlbumArtist(getStringValue("Album Artist"))
    setGenre(getStringValue("Genre"))
    setKind(getStringValue("Kind"))
    setSize(getIntegerValue("Size"))
    setTotalTime(getIntegerValue("Total Time"))
    setDiscNumber(getIntegerValue("Disc Number"))
    setDiscCount(getIntegerValue("Disc Count"))
    setTrackNumber(getIntegerValue("Track Number"))
    setYear(getIntegerValue("Year"))
    setDateModified(getDateValue("Date Modified"))
    setDateAdded(getDateValue("Date Added"))
    setBitRate(getIntegerValue("Bit Rate"))
    setSampleRate(getIntegerValue("Sample Rate"))
    setComments(getStringValue("Comments"))
    setPlayCount(getIntegerValue("Play Count"))
    setPlayDate(getIntegerValue("Play Date"))
    setPlayDateUTC(getDateValue("Play Date UTC"))
    setReleaseDate(getDateValue("Release Date"))
    setSkipCount(getIntegerValue("Skip Count"))
    setSkipDate(getDateValue("Skip Date"))
    setArtworkCount(getIntegerValue("Artwork Count"))
    setSortComposer(getStringValue("Sort Composer"))
    setPersistentID(getStringValue("Persistent ID"))
    setDisabled(getBooleanValue("Disabled"))
    setTrackType(getStringValue("Track Type"))
    setiTunesU(getBooleanValue("iTunesU"))
    setUnplayed(getBooleanValue("Unplayed"))
    setHasVideo(getBooleanValue("Has Video"))
    setHD(getBooleanValue("HD"))
    setVideoWidth(getIntegerValue("Video Width"))
    setVideoHeight(getIntegerValue("Video Height"))
    setMovie(getBooleanValue("Movie"))
    setLocation(getStringValue("Location"))
    setFileFolderCount(getIntegerValue("File Folder Count"))
    setLibraryFolderCount(getIntegerValue("Library Folder Count"))
  }

  /** Track ID */
  Integer trackID
  /** Name */
  String name
  /** Artist */
  String artist
  /** Composer */
  String composer
  /** Album */
  String album
  /** Album Artist */
  String albumArtist
  /** Genre */
  String genre
  /** Kind */
  String kind
  /** Size */
  Integer size
  /** Total Time */
  Integer totalTime
  /** Disc Number */
  Integer discNumber
  /** Disc Count */
  Integer discCount
  /** Track Number */
  Integer trackNumber
  /** Year */
  Integer year
  /** Date Modified */
  Date dateModified
  /** Date Added */
  Date dateAdded
  /** Bit Rate */
  Integer bitRate
  /** Sample Rate */
  Integer sampleRate
  /** Comments */
  String comments
  /** Play Count */
  Integer playCount
  /** Play Date */
  Integer playDate
  /** Play Date UTC */
  Date playDateUTC
  /** Release Date */
  Date releaseDate
  /** Skip Count */
  Integer skipCount
  /** Skip Date */
  Date skipDate
  /** Artwork Count */
  Integer artworkCount
  /** Sort Composer */
  String sortComposer
  /** Persistent ID */
  String persistentID
  /** Disabled */
  Boolean disabled
  /** Track Type */
  String trackType
  /** iTunesU */
  Boolean iTunesU
  /** Unplayed */
  Boolean unplayed
  /** Has Video */
  Boolean hasVideo
  /** HD */
  Boolean HD
  /** Video Width */
  Integer videoWidth
  /** Video Height */
  Integer videoHeight
  /** Movie */
  Boolean movie
  /** Location */
  String location
  /** File Folder Count */
  Integer fileFolderCount
  /** Library Folder Count */
  Integer libraryFolderCount
}

[Groovy] GroovyServ手動管理での導入 for Mac

 Groovy  [Groovy] GroovyServ手動管理での導入 for Mac はコメントを受け付けていません。
12月 302011
 

■環境
Mac OS X 10.7.2

■ユーザガイド
ユーザガイド — GroovyServ v0.9 documentation
http://kobo.github.com/groovyserv/userguide_ja.html

■導入手順
ブラウザからモジュール(以下では、groovyserv-0.9-macosx-x86_64-bin.zip)をdownload。
Download — GroovyServ v0.9 documentation
http://kobo.github.com/groovyserv/download.html


$ sudo mkdir -p /Library/Frameworks/GroovyServ.framework/Versions
$ cd ~/Downloads
$ unzip groovyserv-0.9-macosx-x86_64-bin.zip
$ sudo mv groovyserv-0.9 /Library/Frameworks/GroovyServ.framework/Versions/0.9

$ cd /Library/Frameworks/GroovyServ.framework/Versions
$ sudo ln -s 0.9 Current

$ cd /Library/Frameworks/GroovyServ.framework
$ sudo ln -s Versions/Current Home

$ sudo mkdir /Library/GroovyServ
$ cd /Library/GroovyServ
$ sudo ln -s /Library/Frameworks/GroovyServ.framework/Home Home

$ vi ~/.profile
export JAVA_HOME=/Library/Java/Home
export PATH=$JAVA_HOME/bin:$PATH

export GROOVY_HOME=/Library/Groovy/Home
export PATH=$PATH:$GROOVY_HOME/bin

export GROOVYSERV_HOME=/Library/GroovyServ/Home
export PATH=$PATH:$GROOVYSERV_HOME/bin
alias groovy=groovyclient

$ source ~/.profile

$ groovyclient -v
$ groovy -v

[Groovy] 手動管理での導入 for Mac

 Groovy  [Groovy] 手動管理での導入 for Mac はコメントを受け付けていません。
12月 032011
 

■環境
Mac OS X 10.7.2

■導入手順
ブラウザからモジュール(以下では、groovy-binary-1.8.4.zip)をdownload。
Groovy – Home
http://groovy.codehaus.org/


$ sudo mkdir -p /Library/Frameworks/Groovy.framework/Versions
$ cd ~/Downloads
$ unzip groovy-binary-1.8.4.zip
$ sudo mv groovy-1.8.4 /Library/Frameworks/Groovy.framework/Versions/1.8.4

$ cd /Library/Frameworks/Groovy.framework/Versions
$ sudo ln -s 1.8.4 Current

$ cd /Library/Frameworks/Groovy.framework
$ sudo ln -s Versions/Current Home

$ sudo mkdir /Library/Groovy
$ cd /Library/Groovy
$ sudo ln -s /Library/Frameworks/Groovy.framework/Home Home

$ vi ~/.profile
export JAVA_HOME=/Library/Java/Home
export PATH=$JAVA_HOME/bin:$PATH

export GROOVY_HOME=/Library/Groovy/Home
export PATH=$PATH:$GROOVY_HOME/bin

$ source ~/.profile

$ java -version
$ groovy -v

[Groovy] Jpegファイルを撮影日付きのファイル名に変更

 Groovy  [Groovy] Jpegファイルを撮影日付きのファイル名に変更 はコメントを受け付けていません。
10月 102011
 

■groovy -v
——————————————————
Groovy Version: 1.8.2 JVM: 1.7.0
——————————————————

■RenameToDateShotJpegFile.groovy


import com.drew.imaging.jpeg.JpegMetadataReader
import com.drew.metadata.Directory
import com.drew.metadata.exif.ExifDirectory

/** Config */
File pictureDir = new File("./pictures")

/** Get Jpeg pictures Path */
List<File> pictures = findPictures(pictureDir, ~/.*\.[jJ][pP][gG]/)

/** Rename to DateShot_FileName */
pictures.each{
  dateShot = getDateShot(it)
  if(!it.getName().contains(dateShot)){
    newPath = it.getParent() + File.separator + dateShot + "_" + it.getName()
    it.renameTo(newPath)
  }
}

def getDateShot(File file) {
  Directory directory = JpegMetadataReader.readMetadata(file).getDirectory(ExifDirectory.class)
  dateShot = directory.getString(ExifDirectory.TAG_DATETIME)
  return (dateShot!=null) ? dateShot.replaceAll(/[ |:\/\\?<>"]/,"") : ""
}

def findPictures(File rootDir, java.util.regex.Pattern filter) {
  List<File> pictures = new ArrayList<File>()
  rootDir.traverse(
    type         : groovy.io.FileType.FILES,
    nameFilter   : filter
  ) { 
      pictures.add( it )
  }
  return pictures
}

■実行
groovy -cp metadata-extractor-2.3.1.jar RenameToDateShotJpegFile.groovy

■参考URL
Groovyでファイルツリーを巡り、最初に見つかったファイルを返却するメソッド書いたよ – No Programming, No Life
http://d.hatena.ne.jp/fumokmm/20110911/1315709484

Javaでjpg画像のexif情報をとってみた|ヘビィ・SMD!
http://ameblo.jp/smd310/entry-10854275741.html

[Groovy] RSSのxmlパース

 Groovy  [Groovy] RSSのxmlパース はコメントを受け付けていません。
9月 102011
 

■groovy -v
——————————————————
Groovy Version: 1.8.2 JVM: 1.7.0
——————————————————

■weather_forecast.groovy


rssFeed = new groovy.util.XmlParser().parse("http://weather.yahooapis.com/forecastrss?p=JAXX0099&u=c")
item = rssFeed.channel.item[0]
title = item.title[0].value()[0]
condition = item."yweather:condition"

println "${title} : ${condition.@text[0]}, ${condition.@temp[0]}[℃]"

■実行
// 企業内からなどネット接続時にproxy経由が必要な場合
// set JAVA_OPTS=-Dhttp.proxyHost=proxy.xxxxx.co.jp -Dhttp.proxyPort=8080
groovy weather_forecast.groovy

■結果(標準出力)
——————————————————
Conditions for Yokohama, JA at 9:59 pm JST : Partly Cloudy, 27[℃]
——————————————————

[Groovy] csv2xmlサンプル2

 Groovy  [Groovy] csv2xmlサンプル2 はコメントを受け付けていません。
9月 012011
 

■前回からの変更点
・SQL文を修正
  お酒だけに絞込み、価格の安い順にソート。
  ついでに連番を振りなおす。
・CSVデータが大きいと仮定し、一時ファイルを書きだすように変更。
  ※カレントディレクトリに一時ファイル(dbFile.h2.db)が生成される。

■groovy -v
——————————————————
Groovy Version: 1.8.1 JVM: 1.7.0
——————————————————

■csv2xml.groovy


@Grapes([
    @Grab(group = 'com.h2database', module = 'h2', version = '1.3.157'),
    @GrabConfig(systemClassLoader = true)
])
//jarをロードする場合
//this.getClass().classLoader.rootLoader.addURL(new File("h2-1.3.157.jar").toURL())

import groovy.sql.Sql
import groovy.xml.MarkupBuilder

if(!args) System.exit(1)

memDB = Sql.newInstance("jdbc:h2:./dbFile", "org.h2.Driver")
String sql = """
  select id, name, price, rownum as no from (
    select id, name, CONVERT(price, INT) as price from CSVREAD('${args[0]}',null,'UTF-8') 
    where name like '%酒' order by price
  ) 
"""

xml = new MarkupBuilder()
xml.smartxml() {
  xml.items() {
    memDB.eachRow(sql) {row ->
      xml.item(no:row.no) {
        id(row.id)
        name(row.name)
        price(row.price)
      }
    }
  }
}

memDB.close()

■source.csv(UTF-8)
——————————————————
id, name, price
1, コーラ, 150
2, 葡萄酒, 980
3, 麦酒, 238

——————————————————

■実行
// 企業内からなどネット接続時にproxy経由が必要な場合
// set JAVA_OPTS=-Dhttp.proxyHost=proxy.xxxxx.co.jp -Dhttp.proxyPort=8080
groovy csv2xml.groovy source.csv

■結果(標準出力)
——————————————————
<smartxml>
  <items>
    <item no=’1′>
      <id>3</id>
      <name>麦酒</name>
      <price>238</price>
    </item>
    <item no=’2′>
      <id>2</id>
      <name>葡萄酒</name>
      <price>980</price>
    </item>
  </items>
</smartxml>
——————————————————

[Groovy] csv2xmlサンプル

 Groovy  [Groovy] csv2xmlサンプル はコメントを受け付けていません。
8月 272011
 

■csv2xml.groovy


@Grapes([
    @Grab(group = 'com.h2database', module = 'h2', version = '1.3.157'),
    @GrabConfig(systemClassLoader = true)
])
//jarをロードする場合
//this.getClass().classLoader.rootLoader.addURL(new File("h2-1.3.157.jar").toURL())

import groovy.sql.Sql
import groovy.xml.MarkupBuilder

if(!args) System.exit(1)

memDB = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")
String sql = """
    select * from CSVREAD('${args[0]}',null,'UTF-8')
"""

xml = new MarkupBuilder()
xml.xml() {
  xml.items() {
    memDB.eachRow(sql) {row ->
      xml.item(id:row.id) {
        name(row.name)
        price(row.price)
      }
    }
  }
}

memDB.close()

■source.csv(UTF-8)
————————————————–
id, name, price
1, コーラ, 150
2, 葡萄酒, 980
3, 麦酒, 238

————————————————–

■実行
// 企業内からなどネット接続時にproxy経由が必要な場合
// set JAVA_OPTS=-Dhttp.proxyHost=proxy.xxxxx.co.jp -Dhttp.proxyPort=8080
groovy csv2xml.groovy source.csv

■結果(標準出力)
————————————————–
<xml>
  <items>
    <item id=’1′>
      <name>コーラ</name>
      <price>150</price>
    </item>
    <item id=’2′>
      <name>葡萄酒</name>
      <price>980</price>
    </item>
    <item id=’3′>
      <name>麦酒</name>
      <price>238</price>
    </item>
  </items>
</xml>
————————————————–