content: package jp.aegif.nemaki.bjornloka.load;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  
  import org.apache.commons.collections4.CollectionUtils;
  import com.fasterxml.jackson.core.JsonProcessingException;
  import com.fasterxml.jackson.databind.JsonNode;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.fasterxml.jackson.databind.node.ArrayNode;
  import com.fasterxml.jackson.databind.node.ObjectNode;
  import jp.aegif.nemaki.bjornloka.proxy.CouchProxy;
  import jp.aegif.nemaki.bjornloka.util.Indicator;
  import jp.aegif.nemaki.bjornloka.util.Util;
  
  public abstract class LoadAction {
  	protected String url;
  	protected String repositoryId;
  	protected File file;
  	protected boolean force;
  	
  	protected LoadAction(String url, String repositoryId, File file, boolean force) {
  		super();
  		this.url = Util.sanitizeUrl(url);
  		this.repositoryId = repositoryId;
  		this.file = file;
  		this.force = force;
  	}
  	
  	public static LoadAction getInstance (String url, String repositoryId, File file, boolean force){
  		switch(Util.checkProxyType(url)){
  		case EKTORP: 
  			return new LoadEktorp(url, repositoryId, file, force);
  		case CLOUDANT:
  			return new LoadCloudant(url, repositoryId, file, force);
  		}
  		return null;
  	}
  
  	public abstract boolean load();
  	public abstract boolean initRepository();
  	
  	protected boolean action(CouchProxy proxy, File file, boolean initResult){
  		if(!initResult){
  			System.out.println("Database already exists");
  			return false;
  		}
  		
  		//CouchDB documents(without attachments)
  				List<ObjectNode> documents = new ArrayList<ObjectNode>();
  				//All attachments
  				Map<String,ObjectNode> payloads = new HashMap<String, ObjectNode>();
  		
  		try {
  			//Read all dump data from file
  			JsonNode _dump = new ObjectMapper().readTree(file);
  			ArrayNode dump = (ArrayNode) _dump;
  
  			//Parse each entry in dump
  			Iterator<JsonNode> iterator = dump.iterator();
  			while(iterator.hasNext()){
  				JsonNode _entry = iterator.next();
  				//Document
  				ObjectNode document = (ObjectNode) _entry.get("document");
  				processDocument(document); //remove some fields
  				documents.add(document);
  
  				//Attachments
  				ObjectNode attachments = (ObjectNode) _entry.get("attachments");
  				String docId = document.get("_id").textValue();
  				payloads.put(docId, attachments);
  			}
  		} catch (JsonProcessingException e) {
  			e.printStackTrace();
  			return false;
  		} catch (IOException e) {
  			e.printStackTrace();
  			return false;
  		}
  
  		//Load documents to DB
  		System.out.println("Loading metadata: START");
  		
  		//TEST
  		List<String> documentsResult = new ArrayList<String>();
  		int unit = 5000;
  		int turn = documents.size() / unit;
  		Indicator metadataIndicator = new Indicator(documents.size());
  		for(int i=0; i <= turn ; i++){
  			int toIndex = (unit*(i+1) > documents.size()) ? documents.size() : unit*(i+1);
  			List<ObjectNode> subList = documents.subList(i*unit, toIndex);
  			documentsResult.addAll(proxy.bulkInsert(subList));
  			
  			metadataIndicator.indicate(unit);
  		}
  		
  		if(CollectionUtils.isNotEmpty(documentsResult)){
  			System.err.println("Documents are not imported because of some error.");
  			System.err.println(documentsResult);
  			return false;
  		}
  		System.out.println("Loading metadata: END");
  
  		//Load all attachments to DB
  		System.out.println("Loading attachments: START");
  		Indicator attachmentIndicator = new Indicator(payloads.size());
  		for(Entry<String, ObjectNode> entry : payloads.entrySet()){
  			ObjectNode attachments = entry.getValue();
  			Iterator<String> it = attachments.fieldNames();
  			while(it.hasNext()){
  				String attachmentId = it.next();
  				ObjectNode attachment = (ObjectNode) attachments.get(attachmentId);
  
  				try {
  					proxy.createAttachment(entry.getKey(), attachmentId, attachment);
  				} catch (Exception e) {
  					e.printStackTrace();
  				}
  				
  			}
  			
  			attachmentIndicator.indicate();
  		}
  
  		System.out.println("Loading attachments: END");
  		return true;
  	}
  
  	private static void processDocument(ObjectNode document) {
  		document.remove("_rev");
  		document.remove("_attachments");
  	}
  }
  