View Javadoc

1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.domain.geoloc.importer;
24  
25  import java.io.File;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import org.hibernate.FlushMode;
30  import org.springframework.beans.factory.annotation.Required;
31  
32  import com.gisgraphy.domain.geoloc.entity.Adm;
33  import com.gisgraphy.domain.repository.IAdmDao;
34  import com.gisgraphy.domain.valueobject.GISSource;
35  import com.gisgraphy.domain.valueobject.NameValueDTO;
36  import com.gisgraphy.helper.GeolocHelper;
37  
38  /**
39   * Import the Adm of level 2 file. It is the first step of the adm2 import
40   * process, the import will be complete when all the datastore object will be
41   * updated by the {@link GeonamesFeatureImporter}
42   * 
43   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
44   */
45  public class GeonamesAdm2Importer extends AbstractImporterProcessor {
46  
47      private IAdmDao admDao;
48  
49      /**
50       * Default constructor
51       */
52      public GeonamesAdm2Importer() {
53  	super();
54      }
55  
56      /*
57       * (non-Javadoc)
58       * 
59       * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#processData(java.lang.String)
60       */
61      @Override
62      protected void processData(String line) {
63  	String[] fields = line.split("\t");
64  
65  	/*
66  	 * line table has the following fields :
67  	 * --------------------------------------------------- 0 code : 1 name 2
68  	 * asciiname 3 gisFeatureId
69  	 */
70  
71  	// REM : tha adm2 export format (4 fields) is different from Adm1,3,4 (2
72  	// fields)
73  	checkNumberOfColumn(fields);
74  	// isEmptyField(fields,0,true);
75  	// isEmptyField(fields,1,true);
76  	Adm adm2 = new Adm(2);
77  	adm2.setLocation(GeolocHelper.createPoint(0F, 0F));
78  	if (!isEmptyField(fields, 3, true)) {
79  	    try {
80  		adm2.setFeatureId(new Long(fields[3]));
81  	    } catch (NumberFormatException e) {
82  		logger.warn(fields[3] + " is not a valid gisFeatureId");
83  		return;
84  	    }
85  	} else {
86  	    adm2.setFeatureId((++AbstractImporterProcessor.nbGisInserted) * -1);
87  	}
88  	adm2.setSource(GISSource.GEONAMES);
89  
90  	// process code
91  	if (!isEmptyField(fields, 0, true)) {
92  	    String[] fullAdm2Code = fields[0].split("\\.");
93  	    // check the format
94  	    if (fullAdm2Code.length != 3) {
95  		logger.warn("adm2 importer needs code with 3 fields : "
96  			+ dumpFields(fullAdm2Code) + " is not correct");
97  		return;
98  	    }
99  
100 	    String countryCode = fullAdm2Code[0].toUpperCase();
101 	    String adm1Code = fullAdm2Code[1];
102 	    String adm2Code = fullAdm2Code[2];
103 
104 	    // set the code Value
105 	    if (!isEmptyField(fullAdm2Code, 0, true)) {
106 		adm2.setCountryCode(countryCode);
107 	    }
108 	    if (!isEmptyField(fullAdm2Code, 1, true)) {
109 		adm2.setAdm1Code(adm1Code);
110 	    }
111 	    if (!isEmptyField(fullAdm2Code, 2, true)) {
112 		adm2.setAdm2Code(adm2Code);
113 	    }
114 
115 	    Adm duplicate = this.admDao
116 		    .getAdm2(countryCode, adm1Code, adm2Code);
117 
118 	    if (duplicate != null) {
119 		logger
120 			.warn(adm2
121 				+ " will not be saved because it is duplicate (same codes) with "
122 				+ duplicate);
123 		return;
124 	    }
125 
126 	    // try to get the parent Adm1
127 
128 	    Adm adm1 = null;
129 	    if (false) {
130 		adm1 = this.admDao.suggestMostAccurateAdm(countryCode,
131 			adm1Code, null, null, null, null);
132 		logger.debug("suggested Adm=" + adm1);
133 	    } else {
134 		adm1 = this.admDao.getAdm1(countryCode, adm1Code);
135 	    }
136 
137 	    // if found add to Adm1Childs
138 	    if (adm1 == null) {
139 		logger.warn("could not find adm1 with country=" + countryCode
140 			+ " and code=" + adm1Code + " for adm2 " + adm2);
141 		return;
142 	    } else {
143 		adm1.addChild(adm2);
144 	    }
145 	}
146 
147 	if (!isEmptyField(fields, 2, false)) {
148 	    adm2.setAsciiName(fields[2].trim());
149 	}
150 
151 	if (!isEmptyField(fields, 1, true)) {
152 	    adm2.setName(fields[1].trim());
153 	}
154 
155 	// fallback if asciiName is not null and name is null
156 	if (isEmptyField(fields, 1, false) && !isEmptyField(fields, 2, false)) {
157 	    adm2.setName(fields[2].trim());
158 	}
159 
160 	this.admDao.save(adm2);
161 
162     }
163     
164     /* (non-Javadoc)
165      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#shouldBeSkiped()
166      */
167     @Override
168     protected boolean shouldBeSkipped() {
169 	return !importerConfig.isGeonamesImporterEnabled();
170     }
171 
172     /*
173      * (non-Javadoc)
174      * 
175      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#shouldIgnoreFirstLine()
176      */
177     @Override
178     protected boolean shouldIgnoreFirstLine() {
179 	return false;
180     }
181 
182     /*
183      * (non-Javadoc)
184      * 
185      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#shouldIgnoreComments()
186      */
187     @Override
188     protected boolean shouldIgnoreComments() {
189 	return true;
190     }
191 
192     /*
193      * (non-Javadoc)
194      * 
195      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#setCommitFlushMode()
196      */
197     @Override
198     protected void setCommitFlushMode() {
199 	this.admDao.setFlushMode(FlushMode.COMMIT);
200     }
201 
202     /*
203      * (non-Javadoc)
204      * 
205      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#flushAndClear()
206      */
207     @Override
208     protected void flushAndClear() {
209 	this.admDao.flushAndClear();
210     }
211 
212     /*
213      * (non-Javadoc)
214      * 
215      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#getNumberOfColumns()
216      */
217     @Override
218     protected int getNumberOfColumns() {
219 	return 4;
220     }
221 
222     /**
223      * @param admDao
224      *                The admDao to set
225      */
226     @Required
227     public void setAdmDao(IAdmDao admDao) {
228 	this.admDao = admDao;
229     }
230 
231     /*
232      * (non-Javadoc)
233      * 
234      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#getFiles()
235      */
236     @Override
237     protected File[] getFiles() {
238 	File[] files = new File[1];
239 	files[0] = new File(importerConfig.getGeonamesDir()
240 		+ importerConfig.getAdm2FileName());
241 	return files;
242     }
243 
244     /*
245      * (non-Javadoc)
246      * 
247      * @see com.gisgraphy.domain.geoloc.importer.AbstractImporterProcessor#getMaxInsertsBeforeFlush()
248      */
249     @Override
250     protected int getMaxInsertsBeforeFlush() {
251 	// we commit each times because we don't want duplicate adm and the
252 	// cache is NONSTRICT_READ_WRITE (assynchronous)
253 	return 1;
254     }
255 
256     /*
257      * (non-Javadoc)
258      * 
259      * @see com.gisgraphy.domain.geoloc.importer.IGeonamesProcessor#rollback()
260      */
261     public List<NameValueDTO<Integer>> rollback() {
262 	List<NameValueDTO<Integer>> deletedObjectInfo = new ArrayList<NameValueDTO<Integer>>();
263 	logger.info("deleting adm2...");
264 	int deletedadm = admDao.deleteAllByLevel(2);
265 	if (deletedadm != 0) {
266 	    deletedObjectInfo
267 		    .add(new NameValueDTO<Integer>("ADM2", deletedadm));
268 	}
269 	logger.info(deletedadm + " adm2s have been deleted");
270 	resetStatusFields();
271 	return deletedObjectInfo;
272     }
273 
274 }