UNPKG

vietnam-address-converter

Version:

Thư viện JavaScript/TypeScript để tự động chuyển đổi địa chỉ hành chính Việt Nam từ cũ sang mới theo Nghị quyết 202/2025/QH15

850 lines (845 loc) 33.2 kB
/** * Chuẩn hóa tên địa chỉ để so sánh */ function normalizeText(text) { if (!text) return ''; return text .toLowerCase() .trim() // Loại bỏ dấu tiếng Việt .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') // Loại bỏ các ký tự đặc biệt .replace(/[^\w\s]/g, ' ') // Chuẩn hóa khoảng trắng .replace(/\s+/g, ' ') .trim(); } /** * Tính độ tương đồng giữa 2 chuỗi (Levenshtein distance) */ function calculateSimilarity(str1, str2) { const s1 = normalizeText(str1); const s2 = normalizeText(str2); if (s1 === s2) return 1; if (s1.length === 0 || s2.length === 0) return 0; const matrix = Array(s2.length + 1).fill(null).map(() => Array(s1.length + 1).fill(null)); for (let i = 0; i <= s1.length; i++) matrix[0][i] = i; for (let j = 0; j <= s2.length; j++) matrix[j][0] = j; for (let j = 1; j <= s2.length; j++) { for (let i = 1; i <= s1.length; i++) { const cost = s1[i - 1] === s2[j - 1] ? 0 : 1; matrix[j][i] = Math.min(matrix[j][i - 1] + 1, // insertion matrix[j - 1][i] + 1, // deletion matrix[j - 1][i - 1] + cost // substitution ); } } const maxLength = Math.max(s1.length, s2.length); return (maxLength - matrix[s2.length][s1.length]) / maxLength; } /** * Kiểm tra xem một chuỗi có chứa chuỗi khác hay không (fuzzy match) */ function fuzzyContains(haystack, needle, threshold = 0.8) { const normalizedHaystack = normalizeText(haystack); const normalizedNeedle = normalizeText(needle); if (normalizedHaystack.includes(normalizedNeedle)) return true; // Tìm kiếm từng từ const needleWords = normalizedNeedle.split(' '); const haystackWords = normalizedHaystack.split(' '); return needleWords.every(needleWord => haystackWords.some(haystackWord => calculateSimilarity(haystackWord, needleWord) >= threshold)); } /** * Tìm kết quả tốt nhất dựa trên độ tương đồng */ function findBestMatch(items, searchText, getTextFunction, threshold = 0.7) { let bestMatch = null; for (const item of items) { const itemText = getTextFunction(item); const similarity = calculateSimilarity(searchText, itemText); if (similarity >= threshold && (!bestMatch || similarity > bestMatch.similarity)) { bestMatch = { item, similarity }; } } return bestMatch; } /** * Loại bỏ các từ chỉ loại hình hành chính */ function removeAdministrativeTypes(text) { const types = [ 'thành phố', 'tỉnh', 'quận', 'huyện', 'thị xã', 'thành phố trung ương', 'phường', 'xã', 'thị trấn' ]; let result = normalizeText(text); for (const type of types) { const normalizedType = normalizeText(type); result = result.replace(new RegExp(`\\b${normalizedType}\\b`, 'g'), '').trim(); } return result.replace(/\s+/g, ' ').trim(); } /** * Tách địa chỉ thành các thành phần */ function parseAddress(address) { if (!address) return {}; const parts = address.split(',').map(part => part.trim()).filter(Boolean); if (parts.length === 0) return {}; // Thường thì địa chỉ Việt Nam có format: street, ward, district, province const result = {}; if (parts.length >= 1) { result.province = parts[parts.length - 1]; } if (parts.length >= 2) { result.district = parts[parts.length - 2]; } if (parts.length >= 3) { result.ward = parts[parts.length - 3]; } if (parts.length >= 4) { result.street = parts.slice(0, parts.length - 3).join(', '); } return result; } /** * Optimized DataLoader với cache và indexing */ class OptimizedDataLoader { constructor() { this.rawData = []; this.provinces = []; this.wards = []; this.wardMappings = []; // Caches và indexes để tăng tốc độ tìm kiếm this.provinceNameIndex = new Map(); this.wardNameIndex = new Map(); this.mappingIndex = new Map(); this.normalizedProvinceNames = new Map(); } /** * Load dữ liệu từ thư viện vietnam-address-database với tối ưu hóa */ async loadFromFile(filePath) { try { let data; if (typeof window !== 'undefined') { // Browser environment - fetch from URL throw new Error('OptimizedDataLoader không hỗ trợ browser environment. Sử dụng loadFromUrl() thay thế.'); } if (filePath) { // Load từ file path tùy chỉnh const { readFileSync } = await import('fs'); const rawContent = readFileSync(filePath, 'utf8'); data = JSON.parse(rawContent); } else { // Load từ thư viện vietnam-address-database try { const addressDatabase = await import('vietnam-address-database'); // Thư viện export trực tiếp array dữ liệu data = addressDatabase.default || addressDatabase; } catch (importError) { // Fallback: nếu không import được, thử load từ node_modules const { readFileSync } = await import('fs'); const { join } = await import('path'); const packagePath = join(process.cwd(), 'node_modules', 'vietnam-address-database', 'dist', 'address.json'); const rawContent = readFileSync(packagePath, 'utf8'); data = JSON.parse(rawContent); } } this.rawData = data; this.parseData(); this.buildIndexes(); } catch (error) { throw new Error(`Không thể load dữ liệu: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Load dữ liệu từ URL với tối ưu hóa (cho browser environment) */ async loadFromUrl(url) { try { if (typeof window === 'undefined') { throw new Error('loadFromUrl() chỉ hỗ trợ browser environment. Sử dụng loadFromFile() trong Node.js.'); } const defaultUrl = 'https://unpkg.com/vietnam-address-database@latest/address.json'; // CDN URL for browser const targetUrl = url || defaultUrl; const response = await fetch(targetUrl); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); this.rawData = data; this.parseData(); this.buildIndexes(); } catch (error) { throw new Error(`Không thể load dữ liệu từ URL: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Parse dữ liệu từ raw JSON */ parseData() { for (const item of this.rawData) { if (item.type === 'table' && item.data) { switch (item.name) { case 'provinces': this.provinces = item.data; break; case 'wards': this.wards = item.data; break; case 'ward_mappings': this.wardMappings = item.data; break; } } } } /** * Xây dựng indexes để tăng tốc độ tìm kiếm */ buildIndexes() { console.log('🔧 Building search indexes...'); // Index provinces by normalized names for (const province of this.provinces) { const normalizedName = normalizeText(province.name); const normalizedShortName = normalizeText(province.short_name); this.provinceNameIndex.set(normalizedName, province); this.provinceNameIndex.set(normalizedShortName, province); // Cache normalized names để tránh normalize lại this.normalizedProvinceNames.set(province.name, normalizedName); this.normalizedProvinceNames.set(province.short_name, normalizedShortName); } // Index wards by province code và normalized names for (const ward of this.wards) { const normalizedName = normalizeText(ward.name); const key = `${ward.province_code}_${normalizedName}`; if (!this.wardNameIndex.has(key)) { this.wardNameIndex.set(key, []); } this.wardNameIndex.get(key).push(ward); // Index chỉ theo tên ward (slower fallback) if (!this.wardNameIndex.has(normalizedName)) { this.wardNameIndex.set(normalizedName, []); } this.wardNameIndex.get(normalizedName).push(ward); } // Index mappings by combined keys for (const mapping of this.wardMappings) { const keys = []; if (mapping.old_province_name) { const normalizedProvince = normalizeText(mapping.old_province_name); keys.push(`province_${normalizedProvince}`); if (mapping.old_district_name) { const normalizedDistrict = normalizeText(mapping.old_district_name); keys.push(`district_${normalizedProvince}_${normalizedDistrict}`); if (mapping.old_ward_name) { const normalizedWard = normalizeText(mapping.old_ward_name); keys.push(`ward_${normalizedProvince}_${normalizedDistrict}_${normalizedWard}`); } } } for (const key of keys) { if (!this.mappingIndex.has(key)) { this.mappingIndex.set(key, []); } this.mappingIndex.get(key).push(mapping); } } console.log(`✅ Indexes built: ${this.provinceNameIndex.size} province entries, ${this.wardNameIndex.size} ward entries, ${this.mappingIndex.size} mapping entries`); } /** * Tìm tỉnh theo tên (optimized) */ findProvinceByName(name) { const normalizedName = normalizeText(name); // Tìm exact match trước let province = this.provinceNameIndex.get(normalizedName); if (province) return province; // Fallback: tìm partial match for (const [indexedName, indexedProvince] of this.provinceNameIndex.entries()) { if (indexedName.includes(normalizedName) || normalizedName.includes(indexedName)) { return indexedProvince; } } return undefined; } /** * Tìm phường/xã theo tên và mã tỉnh (optimized) */ findWardByName(name, provinceCode) { const normalizedName = normalizeText(name); if (provinceCode) { // Tìm theo province code trước (faster) const key = `${provinceCode}_${normalizedName}`; const wards = this.wardNameIndex.get(key); if (wards && wards.length > 0) { return wards[0]; } // Fallback: partial match trong province for (const [indexedKey, indexedWards] of this.wardNameIndex.entries()) { if (indexedKey.startsWith(`${provinceCode}_`) && (indexedKey.includes(normalizedName) || normalizedName.includes(indexedKey.split('_')[1]))) { return indexedWards[0]; } } } // Fallback: tìm trong tất cả wards const wards = this.wardNameIndex.get(normalizedName); if (wards && wards.length > 0) { return wards[0]; } return undefined; } /** * Tìm mapping theo thông tin địa chỉ cũ (optimized) */ findMappingByOldAddress(wardName, districtName, provinceName) { if (!provinceName) return []; const normalizedProvince = normalizeText(provinceName); // Tìm theo thứ tự specificity: ward -> district -> province if (wardName && districtName) { const normalizedWard = normalizeText(wardName); const normalizedDistrict = normalizeText(districtName); const key = `ward_${normalizedProvince}_${normalizedDistrict}_${normalizedWard}`; const mappings = this.mappingIndex.get(key); if (mappings && mappings.length > 0) { return mappings; } } if (districtName) { const normalizedDistrict = normalizeText(districtName); const key = `district_${normalizedProvince}_${normalizedDistrict}`; const mappings = this.mappingIndex.get(key); if (mappings && mappings.length > 0) { return mappings; } } // Fallback: chỉ theo province const key = `province_${normalizedProvince}`; const mappings = this.mappingIndex.get(key); return mappings || []; } // Getter methods (unchanged) getProvinces() { return this.provinces; } getWards() { return this.wards; } getWardMappings() { return this.wardMappings; } /** * Get performance stats */ getStats() { return { provinces: this.provinces.length, wards: this.wards.length, mappings: this.wardMappings.length, provinceIndexSize: this.provinceNameIndex.size, wardIndexSize: this.wardNameIndex.size, mappingIndexSize: this.mappingIndex.size }; } } /** * Class chính để chuyển đổi địa chỉ hành chính Việt Nam từ cũ sang mới * Đã được tối ưu hóa với cache và batch processing */ class VietnamAddressConverter { constructor() { this.isInitialized = false; // Caches để tránh tính toán lại this.conversionCache = new Map(); this.provinceCache = new Map(); this.wardCache = new Map(); // Performance tracking this.stats = { totalConversions: 0, cacheHits: 0, avgConversionTime: 0 }; this.dataLoader = new OptimizedDataLoader(); } /** * Khởi tạo với dữ liệu mặc định (Node.js) */ async initialize(dataFilePath) { try { const startTime = performance.now(); await this.dataLoader.loadFromFile(dataFilePath); const endTime = performance.now(); this.isInitialized = true; console.log(`🚀 Converter initialized in ${Math.round(endTime - startTime)}ms`); console.log('📊 Data stats:', this.dataLoader.getStats()); } catch (error) { throw new Error(`Không thể khởi tạo converter: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Khởi tạo với dữ liệu từ URL (Browser) */ async initializeFromUrl(dataUrl) { try { const startTime = performance.now(); await this.dataLoader.loadFromUrl(dataUrl); const endTime = performance.now(); this.isInitialized = true; console.log(`🚀 Converter initialized in ${Math.round(endTime - startTime)}ms`); console.log('📊 Data stats:', this.dataLoader.getStats()); } catch (error) { throw new Error(`Không thể khởi tạo converter: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Chuyển đổi địa chỉ với cache và optimization */ convertAddress(address) { if (!this.isInitialized) { throw new Error('Converter chưa được khởi tạo. Hãy gọi initialize() trước.'); } const startTime = performance.now(); // Tạo cache key từ input const cacheKey = typeof address === 'string' ? address : JSON.stringify(address); // Kiểm tra cache trước if (this.conversionCache.has(cacheKey)) { this.stats.cacheHits++; return this.conversionCache.get(cacheKey); } const fullAddress = typeof address === 'string' ? parseAddress(address) : address; if (!fullAddress.province) { const result = { success: false, originalAddress: fullAddress, message: 'Địa chỉ phải có ít nhất tên tỉnh/thành phố' }; this.conversionCache.set(cacheKey, result); return result; } const validAddress = fullAddress; // Tìm mapping với optimized search const mappings = this.dataLoader.findMappingByOldAddress(validAddress.ward, validAddress.district, validAddress.province); let result; if (mappings.length === 0) { // Sử dụng cached province lookup const newProvinceMatch = this.findNewProvinceCached(validAddress.province); if (newProvinceMatch) { const newWardMatch = this.findNewWardCached(validAddress.ward || '', newProvinceMatch.province_code); if (newWardMatch) { result = { success: true, originalAddress: fullAddress, convertedAddress: { ward: newWardMatch.name, province: newProvinceMatch.name, street: validAddress.street }, mappingInfo: { mappingType: 'unchanged' }, message: 'Địa chỉ không thay đổi (exact match)' }; } else { result = { success: false, originalAddress: fullAddress, message: `Không tìm thấy mapping cho phường/xã: ${validAddress.ward} trong ${newProvinceMatch.name}` }; } } else { result = { success: false, originalAddress: fullAddress, message: `Không tìm thấy tỉnh/thành phố: ${validAddress.province}` }; } } else { // Tìm mapping phù hợp nhất với fast matching const bestMapping = this.findBestMappingFast(validAddress, mappings); if (!bestMapping) { result = { success: false, originalAddress: fullAddress, message: 'Không tìm thấy mapping phù hợp' }; } else { // Xây dựng địa chỉ mới từ mapping const convertedAddress = this.buildConvertedAddress(bestMapping, validAddress.street); result = { success: true, originalAddress: fullAddress, convertedAddress, mappingInfo: { mappingType: 'merged' // simplified mapping type }, message: 'Chuyển đổi thành công' }; } } // Cache result this.conversionCache.set(cacheKey, result); // Update performance stats const endTime = performance.now(); this.stats.totalConversions++; this.stats.avgConversionTime = (this.stats.avgConversionTime * (this.stats.totalConversions - 1) + (endTime - startTime)) / this.stats.totalConversions; return result; } /** * Batch conversion với optimizations */ convertAddresses(addresses) { console.log(`🔄 Converting ${addresses.length} addresses in batch...`); const startTime = performance.now(); const results = addresses.map(address => this.convertAddress(address)); const endTime = performance.now(); console.log(`✅ Batch conversion completed in ${Math.round(endTime - startTime)}ms`); console.log(`📈 Cache hit rate: ${Math.round((this.stats.cacheHits / this.stats.totalConversions) * 100)}%`); return results; } /** * Cached province lookup */ findNewProvinceCached(provinceName) { if (this.provinceCache.has(provinceName)) { return this.provinceCache.get(provinceName); } const province = this.dataLoader.findProvinceByName(provinceName); this.provinceCache.set(provinceName, province); return province; } /** * Cached ward lookup */ findNewWardCached(wardName, provinceCode) { const cacheKey = `${wardName}_${provinceCode || ''}`; if (this.wardCache.has(cacheKey)) { return this.wardCache.get(cacheKey); } const ward = this.dataLoader.findWardByName(wardName, provinceCode); this.wardCache.set(cacheKey, ward); return ward; } /** * Fast mapping selection với simplified scoring */ findBestMappingFast(address, mappings) { if (mappings.length === 1) { return mappings[0]; } let bestMapping = null; let bestScore = 0; const normalizedProvince = normalizeText(address.province); const normalizedDistrict = normalizeText(address.district || ''); const normalizedWard = normalizeText(address.ward || ''); for (const mapping of mappings) { let score = 0; // Fast exact match checks if (mapping.old_province_name && normalizeText(mapping.old_province_name) === normalizedProvince) { score += 10; } if (mapping.old_district_name && normalizeText(mapping.old_district_name) === normalizedDistrict) { score += 10; } if (mapping.old_ward_name && normalizeText(mapping.old_ward_name) === normalizedWard) { score += 20; } // Quick similarity check only if no exact matches if (score === 0) { if (mapping.old_province_name) { score += calculateSimilarity(normalizedProvince, normalizeText(mapping.old_province_name)) * 5; } if (mapping.old_ward_name) { score += calculateSimilarity(normalizedWard, normalizeText(mapping.old_ward_name)) * 10; } } if (score > bestScore) { bestScore = score; bestMapping = mapping; } // Early exit for perfect matches if (score >= 40) break; } return bestScore > 15 ? bestMapping : null; } /** * Build converted address từ mapping */ buildConvertedAddress(mapping, street) { return { ward: mapping.new_ward_name || 'Unknown Ward', province: mapping.new_province_name || 'Unknown Province', street: street }; } /** * Check if address has changes */ hasAddressChanges(oldAddress, newAddress) { const oldNormalized = `${normalizeText(oldAddress.ward || '')}_${normalizeText(oldAddress.province)}`; const newNormalized = `${normalizeText(newAddress.ward || '')}_${normalizeText(newAddress.province || '')}`; return oldNormalized !== newNormalized; } /** * Clear caches để giải phóng memory */ clearCache() { this.conversionCache.clear(); this.provinceCache.clear(); this.wardCache.clear(); console.log('🧹 Caches cleared'); } /** * Get performance statistics */ getPerformanceStats() { return { ...this.stats, cacheSize: this.conversionCache.size, provinceCacheSize: this.provinceCache.size, wardCacheSize: this.wardCache.size, dataStats: this.dataLoader.getStats() }; } // Backward compatibility methods getProvinces() { return this.dataLoader.getProvinces(); } getWards() { return this.dataLoader.getWards(); } getWardMappings() { return this.dataLoader.getWardMappings(); } /** * Lấy thống kê dữ liệu */ getDataStats() { if (!this.isInitialized) { throw new Error('Converter chưa được khởi tạo'); } return this.dataLoader.getStats(); } /** * Lấy danh sách phường/xã theo tỉnh */ getWardsByProvince(provinceCode) { if (!this.isInitialized) { throw new Error('Converter chưa được khởi tạo'); } return this.dataLoader.getWards().filter((ward) => ward.province_code === provinceCode); } /** * Tìm kiếm mapping theo từ khóa */ searchMappings(keyword) { if (!this.isInitialized) { throw new Error('Converter chưa được khởi tạo'); } normalizeText(keyword); return this.dataLoader.getWardMappings().filter((mapping) => { const searchText = `${mapping.old_ward_name} ${mapping.old_district_name} ${mapping.old_province_name} ${mapping.new_ward_name} ${mapping.new_province_name}`; return fuzzyContains(searchText, keyword, 0.6); }); } } /** * Class để load và parse dữ liệu từ thư viện vietnam-address-database */ class DataLoader { constructor() { this.rawData = []; this.provinces = []; this.wards = []; this.wardMappings = []; } /** * Load dữ liệu từ thư viện vietnam-address-database */ async loadFromFile(filePath) { try { let data; if (typeof window !== 'undefined') { // Browser environment - fetch from URL throw new Error('DataLoader không hỗ trợ browser environment. Sử dụng loadFromUrl() thay thế.'); } if (filePath) { // Load từ file path tùy chỉnh const { readFileSync } = await import('fs'); const rawContent = readFileSync(filePath, 'utf8'); data = JSON.parse(rawContent); } else { // Load từ thư viện vietnam-address-database try { const addressDatabase = await import('vietnam-address-database'); // Thư viện export trực tiếp array dữ liệu data = addressDatabase.default || addressDatabase; } catch (importError) { // Fallback: nếu không import được, thử load từ node_modules const { readFileSync } = await import('fs'); const { join } = await import('path'); const packagePath = join(process.cwd(), 'node_modules', 'vietnam-address-database', 'dist', 'address.json'); const rawContent = readFileSync(packagePath, 'utf8'); data = JSON.parse(rawContent); } } this.rawData = data; this.parseData(); } catch (error) { throw new Error(`Không thể load dữ liệu: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Load dữ liệu từ URL (cho browser environment) */ async loadFromUrl(url) { try { if (typeof window === 'undefined') { throw new Error('loadFromUrl() chỉ hỗ trợ browser environment. Sử dụng loadFromFile() trong Node.js.'); } const defaultUrl = 'https://unpkg.com/vietnam-address-database@latest/address.json'; // CDN URL for browser const targetUrl = url || defaultUrl; const response = await fetch(targetUrl); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); this.rawData = data; this.parseData(); } catch (error) { throw new Error(`Không thể load dữ liệu từ URL: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Parse dữ liệu từ raw JSON thành các đối tượng có cấu trúc */ parseData() { for (const item of this.rawData) { if (item.type === 'table' && item.data) { switch (item.name) { case 'provinces': this.provinces = item.data; break; case 'wards': this.wards = item.data; break; case 'ward_mappings': this.wardMappings = item.data; break; } } } } /** * Lấy danh sách tỉnh/thành phố */ getProvinces() { return this.provinces; } /** * Lấy danh sách phường/xã */ getWards() { return this.wards; } /** * Lấy danh sách mapping */ getWardMappings() { return this.wardMappings; } /** * Tìm tỉnh theo tên */ findProvinceByName(name) { const normalizedName = name.toLowerCase().trim(); return this.provinces.find(province => { const provinceName = province.name.toLowerCase(); const shortName = province.short_name.toLowerCase(); return provinceName.includes(normalizedName) || shortName.includes(normalizedName) || normalizedName.includes(provinceName) || normalizedName.includes(shortName); }); } /** * Tìm phường/xã theo tên và mã tỉnh */ findWardByName(name, provinceCode) { const normalizedName = name.toLowerCase().trim(); let wards = this.wards; if (provinceCode) { wards = wards.filter(ward => ward.province_code === provinceCode); } return wards.find(ward => { const wardName = ward.name.toLowerCase(); return wardName.includes(normalizedName) || normalizedName.includes(wardName); }); } /** * Tìm mapping theo thông tin địa chỉ cũ */ findMappingByOldAddress(wardName, districtName, provinceName) { let mappings = this.wardMappings; if (provinceName) { const normalizedProvince = provinceName.toLowerCase().trim(); mappings = mappings.filter(mapping => { if (!mapping.old_province_name) return false; return mapping.old_province_name.toLowerCase().includes(normalizedProvince) || normalizedProvince.includes(mapping.old_province_name.toLowerCase()); }); } if (districtName) { const normalizedDistrict = districtName.toLowerCase().trim(); mappings = mappings.filter(mapping => { if (!mapping.old_district_name) return false; return mapping.old_district_name.toLowerCase().includes(normalizedDistrict) || normalizedDistrict.includes(mapping.old_district_name.toLowerCase()); }); } if (wardName) { const normalizedWard = wardName.toLowerCase().trim(); mappings = mappings.filter(mapping => { if (!mapping.old_ward_name) return false; return mapping.old_ward_name.toLowerCase().includes(normalizedWard) || normalizedWard.includes(mapping.old_ward_name.toLowerCase()); }); } return mappings; } /** * Kiểm tra xem dữ liệu đã được load chưa */ isDataLoaded() { return this.provinces.length > 0 && this.wards.length > 0 && this.wardMappings.length > 0; } /** * Lấy thống kê dữ liệu */ getDataStats() { return { provinces: this.provinces.length, wards: this.wards.length, mappings: this.wardMappings.length }; } } export { DataLoader, OptimizedDataLoader, VietnamAddressConverter, calculateSimilarity, findBestMatch, fuzzyContains, normalizeText, parseAddress, removeAdministrativeTypes };