001/* 002 * Shredzone Commons - pdb 003 * 004 * Copyright (C) 2009 Richard "Shred" Körber 005 * http://commons.shredzone.org 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU Library General Public License as 009 * published by the Free Software Foundation, either version 3 of the 010 * License, or (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU Library General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package org.shredzone.commons.pdb.converter; 021 022import java.io.IOException; 023 024import org.shredzone.commons.pdb.PdbDatabase; 025import org.shredzone.commons.pdb.PdbFile; 026import org.shredzone.commons.pdb.appinfo.AddressAppInfo; 027import org.shredzone.commons.pdb.record.AddressRecord; 028 029/** 030 * A {@link Converter} that reads Address records. 031 * 032 * @see <a href="http://search.cpan.org/~bdfoy/p5-Palm-1.011/lib/Address.pm">Palm::Address</a> 033 */ 034public class AddressConverter implements Converter<AddressRecord, AddressAppInfo> { 035 036 private static final String[] COUNTRIES = { "AU", "AT", "BE", "BR", "CA", 037 "DK", "FI", "FR", "DE", "HK", "IS", "IE", "IT", "JP", "LU", "MX", 038 "NL", "NZ", "NO", "ES", "SE", "CH", "GB", "US", }; 039 040 private static final AddressRecord.Label[] PHONE_LABELS = { 041 AddressRecord.Label.PHONE1, AddressRecord.Label.PHONE2, 042 AddressRecord.Label.PHONE3, AddressRecord.Label.PHONE4, 043 AddressRecord.Label.PHONE5, AddressRecord.Label.PHONE6, 044 AddressRecord.Label.PHONE7, AddressRecord.Label.PHONE8, 045 }; 046 047 private static final int LABEL_LENGTH = 16; 048 049 @Override 050 public boolean isAcceptable( 051 PdbDatabase<AddressRecord, AddressAppInfo> database) { 052 return "AddressDB".equals(database.getName()) 053 && "addr".equals(database.getCreator()); 054 } 055 056 @Override 057 public AddressRecord convert(PdbFile reader, int record, int size, int attribute, 058 PdbDatabase<AddressRecord, AddressAppInfo> database) 059 throws IOException { 060 061 AddressRecord result = new AddressRecord(attribute); 062 if (result.isDelete()) { 063 return null; 064 } 065 066 int phoneFlags = reader.readInt(); 067 int fieldMap = reader.readInt(); 068 reader.readByte(); 069 070 AddressRecord.Field[] fields = AddressRecord.Field.values(); 071 AddressRecord.Label[] labels = AddressRecord.Label.values(); 072 for (int ix = 0; ix < fields.length; ix++) { 073 if ((fieldMap & (1 << ix)) != 0) { 074 result.setLabel(fields[ix], mapLabel(labels[ix], phoneFlags)); 075 result.setField(fields[ix], reader.readTerminatedString()); 076 } 077 } 078 079 result.setDisplayPhone((phoneFlags >> 20) & 0x0F); 080 081 return result; 082 } 083 084 /** 085 * Maps a phone label to the one selected in the phone flags. 086 * 087 * @param label 088 * Label to be mapped 089 * @param flags 090 * Phone flags 091 * @return Mapped label 092 * @throws IOException 093 * if the flags were not readable 094 */ 095 private AddressRecord.Label mapLabel(AddressRecord.Label label, int flags) 096 throws IOException { 097 try { 098 switch (label) { 099 case PHONE1: return PHONE_LABELS[flags & 0x0F]; 100 case PHONE2: return PHONE_LABELS[(flags >> 4) & 0x0F]; 101 case PHONE3: return PHONE_LABELS[(flags >> 8) & 0x0F]; 102 case PHONE4: return PHONE_LABELS[(flags >> 12) & 0x0F]; 103 case PHONE5: return PHONE_LABELS[(flags >> 16) & 0x0F]; 104 default: return label; 105 } 106 } catch (ArrayIndexOutOfBoundsException e) { //NOSONAR 107 throw new IOException("unknown mapping for label " + label); 108 } 109 } 110 111 @Override 112 public AddressAppInfo convertAppInfo(PdbFile reader, int size, 113 PdbDatabase<AddressRecord, AddressAppInfo> database) 114 throws IOException { 115 AddressAppInfo result = new AddressAppInfo(); 116 reader.readCategories(result); 117 118 reader.readShort(); 119 reader.readInt(); 120 121 for (AddressRecord.Label label : AddressRecord.Label.values()) { 122 result.setLabel(label, reader.readTerminatedFixedString(LABEL_LENGTH)); 123 } 124 125 int country = reader.readByte(); 126 if (country >= 0 && country < COUNTRIES.length) { 127 result.setCountry(COUNTRIES[country]); 128 } 129 130 reader.readByte(); 131 132 return result; 133 } 134 135}