/*
 * This file is part of NixNote/NeighborNote 
 * Copyright 2009 Randy Baumgarte
 * 
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/

package cx.fbn.nevernote.xml;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import com.evernote.edam.type.Data;
import com.evernote.edam.type.LinkedNotebook;
import com.evernote.edam.type.Note;
import com.evernote.edam.type.NoteAttributes;
import com.evernote.edam.type.NoteSortOrder;
import com.evernote.edam.type.Notebook;
import com.evernote.edam.type.Publishing;
import com.evernote.edam.type.Resource;
import com.evernote.edam.type.ResourceAttributes;
import com.evernote.edam.type.SavedSearch;
import com.evernote.edam.type.SharedNotebook;
import com.evernote.edam.type.Tag;
import com.trolltech.qt.core.QByteArray;
import com.trolltech.qt.core.QFile;
import com.trolltech.qt.core.QIODevice;
import com.trolltech.qt.gui.QIcon;
import com.trolltech.qt.gui.QImage;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.xml.QXmlStreamAttributes;
import com.trolltech.qt.xml.QXmlStreamReader;

import cx.fbn.nevernote.evernote.NoteMetadata;
import cx.fbn.nevernote.sql.DatabaseConnection;
import cx.fbn.nevernote.utilities.ApplicationLogger;

public class ImportData {

	public int							lastError;
	private String						errorMessage;
	private String						fileName;
	DatabaseConnection					conn;
	QXmlStreamReader					reader;
	private Note						note;
	private boolean						noteIsDirty;
	private Notebook					notebook;
	private boolean						notebookIsDirty;
	private boolean						notebookIsLocal;
	private boolean						notebookIsReadOnly;
	private QIcon						notebookIcon;
	private Tag							tag;
	private boolean						tagIsDirty;
//	private final HashMap<String,Integer>		titleColors;
	private SavedSearch					search;
	private boolean						searchIsDirty;
	public int							highUpdateSequenceNumber;
	public long							lastSequenceDate;
	private final ApplicationLogger 	logger;
	private final boolean				backup;
	private String						notebookGuid;
	private boolean						linkedNotebookIsDirty;
	private boolean						sharedNotebookIsDirty;
	private LinkedNotebook				linkedNotebook;
	private SharedNotebook				sharedNotebook;
	public final boolean				importTags = false;
	public final boolean				importNotebooks = false;
	private final HashMap<String,String>		noteMap;
	private final HashMap<String, NoteMetadata> metaData;
	
	public ImportData(DatabaseConnection c, boolean full) {
		logger = new ApplicationLogger("import.log");
		backup = full;
		conn = c;
		metaData = new HashMap<String,NoteMetadata>();
		noteMap = new HashMap<String,String>();
	}
	
	public void importData(String f) {
		fileName = f;
		errorMessage = "";
				
		lastError = 0;
		errorMessage = "";
		QFile xmlFile = new QFile(fileName);
		if (!xmlFile.open(QIODevice.OpenModeFlag.ReadOnly)) {
			lastError = 16;
			errorMessage = "Cannot open file.";
		}
			
		reader = new QXmlStreamReader(xmlFile);	
		while (!reader.atEnd()) {
			reader.readNext();
			if (reader.hasError()) {
				errorMessage = reader.errorString();
				logger.log(logger.LOW, "************************* ERROR READING BACKUP " +reader.errorString());
				lastError = 16;
				return;
			}
			if (reader.name().equalsIgnoreCase("nevernote-export") && reader.isStartElement()) {
				QXmlStreamAttributes attributes = reader.attributes();
				String version = attributes.value("version");
				String type = attributes.value("exportType");
				String application = attributes.value("application");
				if (!version.equalsIgnoreCase("0.85") && !version.equalsIgnoreCase("0.86")
						&& !version.equalsIgnoreCase("0.95")) {
					lastError = 1;
					errorMessage = "Unknown backup version = " +version;
					return;
				}
				if (!application.equalsIgnoreCase("NeverNote")) {
					lastError = 2;
					errorMessage = "This backup is from an unknown application = " +application;
					return;
				}
				if (!type.equalsIgnoreCase("backup") && backup) {
					lastError = 4;
					errorMessage = "This is an export file, not a backup file";
					return;
				} 
				if (type.equalsIgnoreCase("export") && backup) {
					lastError = 5;
					errorMessage = "This is a backup file, not an export file";		
					return;
				}
				
			}
			if (reader.name().equalsIgnoreCase("Synchronization") && reader.isStartElement() && backup) {
				processSynchronizationNode();
				conn.getSyncTable().setLastSequenceDate(lastSequenceDate);
		    	conn.getSyncTable().setUpdateSequenceNumber(highUpdateSequenceNumber);
			}
			if (reader.name().equalsIgnoreCase("note") && reader.isStartElement()) {
				processNoteNode();
				if (backup)
					conn.getNoteTable().addNote(note, noteIsDirty);
				else {
					note.setUpdateSequenceNum(0);
					if (notebookGuid != null) 
						note.setNotebookGuid(notebookGuid);
					for (int i=0; i<note.getResourcesSize(); i++) {
						note.getResources().get(i).setUpdateSequenceNum(0);
					}
					conn.getNoteTable().addNote(note, true);
				}
				if (metaData.containsKey(note.getGuid())) 
					conn.getNoteTable().updateNoteMetadata(metaData.get(note.getGuid()));
			}
			if (reader.name().equalsIgnoreCase("notebook") && reader.isStartElement() && (backup || importNotebooks)) {
				processNotebookNode();
	    		String existingGuid = conn.getNotebookTable().findNotebookByName(notebook.getName());
	    		if (existingGuid == null) {
	    			conn.getNotebookTable().addNotebook(notebook, notebookIsDirty, notebookIsLocal);
	    		} else {
	    			conn.getNotebookTable().updateNotebookGuid(existingGuid, notebook.getGuid());
	    			conn.getNotebookTable().updateNotebook(notebook, notebookIsDirty);
	    		}
	    		conn.getNotebookTable().setIcon(notebook.getGuid(), notebookIcon, "PNG");
	    		conn.getNotebookTable().setReadOnly(notebook.getGuid(), notebookIsReadOnly);
			}
			if (reader.name().equalsIgnoreCase("tag") && reader.isStartElement() && (backup || importTags)) {
				processTagNode();
		   		String testGuid = conn.getTagTable().findTagByName(tag.getName());
	    		if (testGuid == null)
	    			conn.getTagTable().addTag(tag, tagIsDirty);
	    		else {
	    			conn.getTagTable().updateTagGuid(testGuid, tag.getGuid());
	    			conn.getTagTable().updateTag(tag,tagIsDirty);
	    		}
			}
			if (reader.name().equalsIgnoreCase("savedsearch") && reader.isStartElement() && backup) {
				processSavedSearchNode();
	    		conn.getSavedSearchTable().addSavedSearch(search, searchIsDirty);
			}
			if (reader.name().equalsIgnoreCase("LinkedNotebook") && reader.isStartElement() && backup) {
				processLinkedNotebookNode();
	    		conn.getLinkedNotebookTable().addNotebook(linkedNotebook, linkedNotebookIsDirty);
			}
			if (reader.name().equalsIgnoreCase("SharedNotebook") && reader.isStartElement() && backup) {
				processSharedNotebookNode();
	    		conn.getSharedNotebookTable().addNotebook(sharedNotebook, sharedNotebookIsDirty);
			}
		}
		xmlFile.close();
	}
	
	
	private void processNoteNode() {
		note = new Note();
		note.setResources(new ArrayList<Resource>());

		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Guid")) { 
					note.setGuid(textValue());
					if (!backup) {
						Random random1 = new Random();
						String newGuid = "IMP" +new Integer(random1.nextInt(1000)).toString();
						newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
						newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
						newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
						noteMap.put(note.getGuid(), newGuid);
						note.setGuid(newGuid);
					} else 
						noteMap.put(note.getGuid(), note.getGuid());
				}
				if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
					note.setUpdateSequenceNum(intValue());
				if (reader.name().equalsIgnoreCase("Title")) 
					note.setTitle(textValue());
				if (reader.name().equalsIgnoreCase("Created")) 
					note.setCreated(longValue());
				if (reader.name().equalsIgnoreCase("Updated")) 
					note.setUpdated(longValue());
				if (reader.name().equalsIgnoreCase("Deleted")) 
					note.setDeleted(longValue());
				if (reader.name().equalsIgnoreCase("Active")) 
					note.setActive(booleanValue());
				if (reader.name().equalsIgnoreCase("NotebookGuid")) 
					note.setNotebookGuid(textValue());
				if (reader.name().equalsIgnoreCase("Content")) 
					note.setContent(textValue());
				if (reader.name().equalsIgnoreCase("NoteTags")) 
					note.setTagGuids(processNoteTagList());
				if (reader.name().equalsIgnoreCase("NoteAttributes")) 
					note.setAttributes(processNoteAttributes());
				if (reader.name().equalsIgnoreCase("NoteResource")) 
					note.getResources().add(processResource());
				if (reader.name().equalsIgnoreCase("Dirty")) {
					if (booleanValue())
						noteIsDirty=true;
				}
				if (reader.name().equalsIgnoreCase("TitleColor")) {
					if (metaData.get(note.getGuid()) == null) {
						NoteMetadata m = new NoteMetadata();
						m.setColor(intValue());
						metaData.put(note.getGuid(), m);
					} else
						metaData.get(note.getGuid()).setColor(intValue());
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("note") && reader.isEndElement())
				atEnd = true;
		}
		
		return;
		
	}	
	private Resource processResource() {
		Resource resource = new Resource();
		boolean atEnd = false;
		boolean isDirty = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Guid")) 
					resource.setGuid(textValue());
				if (!backup) {
					Random random1 = new Random();
					String newGuid = "IMP" +new Integer(random1.nextInt(1000)).toString();
					newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
					newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
					newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();
					resource.setGuid(newGuid);
				}
				if (reader.name().equalsIgnoreCase("NoteGuid")) {
					String tx = textValue();
					resource.setNoteGuid(noteMap.get(textValue()));  
					resource.setNoteGuid(noteMap.get(tx));
				}
				if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
					resource.setUpdateSequenceNum(intValue());
				if (reader.name().equalsIgnoreCase("Active")) 
					resource.setActive(booleanValue());
				if (reader.name().equalsIgnoreCase("Mime")) 
					resource.setMime(textValue());
				if (reader.name().equalsIgnoreCase("Duration")) 
					resource.setDuration(shortValue());
				if (reader.name().equalsIgnoreCase("Height")) 
					resource.setHeight(shortValue());
				if (reader.name().equalsIgnoreCase("Width")) 
					resource.setWidth(shortValue());
				if (reader.name().equalsIgnoreCase("dirty")) 
					isDirty = booleanValue();
				if (reader.name().equalsIgnoreCase("Data")) 
					resource.setData(processData("Data"));
				if (reader.name().equalsIgnoreCase("AlternateData")) 
					resource.setAlternateData(processData("AlternateData"));
				if (reader.name().equalsIgnoreCase("RecognitionData")) 
					resource.setRecognition(processData("RecognitionData"));
				if (reader.name().equalsIgnoreCase("NoteResourceAttribute")) 
					resource.setAttributes(processResourceAttributes());
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("noteresource") && reader.isEndElement())
				atEnd = true;
		}
		
		conn.getNoteTable().noteResourceTable.saveNoteResource(resource, isDirty);

		
		return resource;
	}
	
	private Data processData(String nodeName) {
		Data data = new Data();
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Size")) 
					data.setSize(intValue());
				if (reader.name().equalsIgnoreCase("Body")) {
					byte[] b = textValue().getBytes();   // data binary
					QByteArray hexData = new QByteArray(b);
					QByteArray binData = new QByteArray(QByteArray.fromHex(hexData));
					data.setBody(binData.toByteArray());
				}
				if (reader.name().equalsIgnoreCase("BodyHash")) {
					byte[] b = textValue().getBytes();   // data binary
					QByteArray hexData = new QByteArray(b);
					QByteArray binData = new QByteArray(QByteArray.fromHex(hexData));
					data.setBodyHash(binData.toByteArray());
				}

				reader.readNext();
				if (reader.name().equalsIgnoreCase("data") && reader.isEndElement())
					atEnd = true;
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase(nodeName) && reader.isEndElement())
				atEnd = true;
		}
		return data;
	}

	private ResourceAttributes processResourceAttributes() {
		ResourceAttributes attributes = new ResourceAttributes();
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("CameraMake")) 
					attributes.setCameraMake(textValue());		
				if (reader.name().equalsIgnoreCase("CameraModel")) 
					attributes.setCameraModel(textValue());		
				if (reader.name().equalsIgnoreCase("FileName")) 
					attributes.setFileName(textValue());		
				if (reader.name().equalsIgnoreCase("RecoType")) 
					attributes.setRecoType(textValue());		
				if (reader.name().equalsIgnoreCase("CameraModel")) 
					attributes.setCameraMake(textValue());		
				if (reader.name().equalsIgnoreCase("SourceURL")) 
					attributes.setSourceURL(textValue());		
				if (reader.name().equalsIgnoreCase("Altitude")) 
					attributes.setAltitude(doubleValue());		
				if (reader.name().equalsIgnoreCase("Longitude")) 
					attributes.setLongitude(doubleValue());		
				if (reader.name().equalsIgnoreCase("Latitude")) 
					attributes.setLatitude(doubleValue());		
				if (reader.name().equalsIgnoreCase("Timestamp")) 
					attributes.setTimestamp(longValue());		
				if (reader.name().equalsIgnoreCase("Attachment")) 
					attributes.setAttachment(booleanValue());		
				if (reader.name().equalsIgnoreCase("ClientWillIndex")) 
					attributes.setClientWillIndex(booleanValue());		
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("noteresourceattribute") && reader.isEndElement())
				atEnd = true;
		}
		
		return attributes;
	}

	
	private List<String> processNoteTagList() {
		List<String> guidList = new ArrayList<String>();
	

		boolean atEnd = false;
		while(!atEnd) {			
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("guid")) 
					guidList.add(textValue());
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("notetags") && reader.isEndElement())
				atEnd = true;
		}
			return guidList;
	}



	private NoteAttributes processNoteAttributes() {
	NoteAttributes attributes = new NoteAttributes();
	
	boolean atEnd = false;
	while(!atEnd) {
		if (reader.isStartElement()) {
			if (reader.name().equalsIgnoreCase("Author")) 
				attributes.setAuthor(textValue());
			if (reader.name().equalsIgnoreCase("SourceURL")) 
				attributes.setSourceURL(textValue());
			if (reader.name().equalsIgnoreCase("Source")) 
				attributes.setSource(textValue());
			if (reader.name().equalsIgnoreCase("SourceApplication")) 
				attributes.setSourceApplication(textValue());
			if (reader.name().equalsIgnoreCase("Altitude")) 
				attributes.setAltitude(doubleValue());
			if (reader.name().equalsIgnoreCase("Longitude")) 
				attributes.setLongitude(doubleValue());
			if (reader.name().equalsIgnoreCase("Latitude")) 
				attributes.setLatitude(doubleValue());
			if (reader.name().equalsIgnoreCase("SubjectDate")) 
				attributes.setSubjectDate(longValue());
		}
		reader.readNext();
		if (reader.name().equalsIgnoreCase("noteattributes") && reader.isEndElement())
			atEnd = true;
	}
	
	return attributes;
}

	
	private void processSynchronizationNode() {
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 	
					highUpdateSequenceNumber = intValue();
				if (reader.name().equalsIgnoreCase("LastSequenceDate")) 	
					lastSequenceDate = longValue();
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("synchronization") && reader.isEndElement())
				atEnd = true;
		}		
	}
	
	
	private void processSavedSearchNode() {
		search = new SavedSearch();
		searchIsDirty = false;
		
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Guid")) 
					search.setGuid(textValue());
				if (reader.name().equalsIgnoreCase("Name")) 
					search.setName(textValue());
				if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
					search.setUpdateSequenceNum(intValue());
				if (reader.name().equalsIgnoreCase("Query")) 
					search.setQuery(textValue());
				if (reader.name().equalsIgnoreCase("Dirty")) {
					if (booleanValue())
						searchIsDirty = true;
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("savedsearch") && reader.isEndElement())
				atEnd = true;		}	
		return;
	}
	
	
	private void processLinkedNotebookNode() {
		linkedNotebook = new LinkedNotebook();
		linkedNotebookIsDirty = false;
		
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Guid")) 
					linkedNotebook.setGuid(textValue());
				if (reader.name().equalsIgnoreCase("ShardID")) 
					linkedNotebook.setShardId(textValue());
				if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
					linkedNotebook.setUpdateSequenceNum(intValue());
				if (reader.name().equalsIgnoreCase("ShareKey")) 
					linkedNotebook.setShareKey(textValue());
				if (reader.name().equalsIgnoreCase("ShareName")) 
					linkedNotebook.setShareName(textValue());
				if (reader.name().equalsIgnoreCase("Uri")) 
					linkedNotebook.setUri(textValue());
				if (reader.name().equalsIgnoreCase("Username")) 
					linkedNotebook.setUsername(textValue());
				if (reader.name().equalsIgnoreCase("Dirty")) {
					if (booleanValue())
						linkedNotebookIsDirty = true;
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("LinkedNotebook") && reader.isEndElement())
				atEnd = true;		}	
		return;
	}


	private void processSharedNotebookNode() {
		sharedNotebook = new SharedNotebook();
		sharedNotebookIsDirty = false;
		
		boolean atEnd = false;
		while(!atEnd) {
			if (reader.isStartElement()) {
				if (reader.name().equalsIgnoreCase("Id")) 
					sharedNotebook.setId(intValue());
				if (reader.name().equalsIgnoreCase("Userid")) 
					sharedNotebook.setUserId(intValue());
				if (reader.name().equalsIgnoreCase("Email")) 
					sharedNotebook.setEmail(textValue());
				if (reader.name().equalsIgnoreCase("NotebookGuid")) 
					sharedNotebook.setNotebookGuid(textValue());
				if (reader.name().equalsIgnoreCase("ShareKey")) 
					sharedNotebook.setShareKey(textValue());
				if (reader.name().equalsIgnoreCase("Username")) 
					sharedNotebook.setUsername(textValue());
				if (reader.name().equalsIgnoreCase("ServiceCreated")) 
					sharedNotebook.setServiceCreated(longValue());
				if (reader.name().equalsIgnoreCase("Dirty")) {
					if (booleanValue())
						sharedNotebookIsDirty = true;
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("LinkedNotebook") && reader.isEndElement())
				atEnd = true;		}	
		return;
	}

	

	
	private void processNotebookNode() {
		notebook = new Notebook();
		Publishing p = new Publishing();
		notebook.setPublishing(p);
		notebookIsDirty = false;
		notebookIsLocal = false;
		notebookIsReadOnly = false;
		notebookIcon = null;
		boolean atEnd = false;
		while(!atEnd) {
			if (backup || importNotebooks) {
				if (reader.isStartElement()) {
					if (reader.name().equalsIgnoreCase("Guid")) 
						notebook.setGuid(textValue());
					if (reader.name().equalsIgnoreCase("Name")) 
						notebook.setName(textValue());
					if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
						notebook.setUpdateSequenceNum(intValue());
					if (reader.name().equalsIgnoreCase("ServiceCreated")) 
						notebook.setServiceCreated(longValue());
					if (reader.name().equalsIgnoreCase("ServiceUpdated")) 
						notebook.setServiceUpdated(longValue());
					if (reader.name().equalsIgnoreCase("DefaultNotebook")) {
						notebook.setDefaultNotebook(booleanValue());
					}
					if (reader.name().equalsIgnoreCase("Dirty")) {
						if (booleanValue())
							notebookIsDirty = true;
					}
					if (reader.name().equalsIgnoreCase("LocalNotebook")) {
						if (booleanValue())
							notebookIsLocal = true;
					}
					if (reader.name().equalsIgnoreCase("ReadOnly")) {
						if (booleanValue())
							notebookIsReadOnly = true;
					}
					if (reader.name().equalsIgnoreCase("PublishingPublicDescription")) {
						notebook.getPublishing().setPublicDescription(textValue());
					}
					if (reader.name().equalsIgnoreCase("PublishingUri")) {
						notebook.getPublishing().setUri(textValue());
					}
					if (reader.name().equalsIgnoreCase("PublishingOrder")) {
						notebook.getPublishing().setOrder(NoteSortOrder.findByValue(intValue()));
					}
					if (reader.name().equalsIgnoreCase("ReadOnly")) {
						if (booleanValue())
							notebookIsReadOnly = true;
					}
					if (reader.name().equalsIgnoreCase("PublishingAscending")) {
						if (booleanValue())
							notebook.getPublishing().setAscending(true);
						else
							notebook.getPublishing().setAscending(false);
					}		
					if (reader.name().equalsIgnoreCase("Icon")) {
						byte[] b = textValue().getBytes();   // data binary
						QByteArray hexData = new QByteArray(b);
						QByteArray binData = new QByteArray(QByteArray.fromHex(hexData));
						notebookIcon = new QIcon(QPixmap.fromImage(QImage.fromData(binData)));
					}
					if (reader.name().equalsIgnoreCase("Stack"))
						notebook.setStack(textValue());
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("notebook") && reader.isEndElement())
				atEnd = true;
		}
		return;
	}

	
	
	private void processTagNode() {
		tag = new Tag();
		tagIsDirty = false;
		boolean atEnd = false;
		while(!atEnd) {
			if (backup || importTags) {
				if (reader.isStartElement()) {			
					if (reader.name().equalsIgnoreCase("Guid")) 
						tag.setGuid(textValue());
					if (reader.name().equalsIgnoreCase("Name")) 
						tag.setName(textValue());
					if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) 
						tag.setUpdateSequenceNum(intValue());
					if (reader.name().equalsIgnoreCase("ParentGuid")) 
						tag.setParentGuid(textValue());
					if (reader.name().equalsIgnoreCase("Dirty")) {
						if (booleanValue())
							tagIsDirty = true;
					}
				}
			}
			reader.readNext();
			if (reader.name().equalsIgnoreCase("tag") && reader.isEndElement())
				atEnd = true;
		}
		return;
	}
	
	
	
	
	private String textValue() {
		return reader.readElementText();
	}
	private int intValue() {
		return new Integer(textValue());
	}
	private long longValue() {
		return new Long(textValue());
	}
	private double doubleValue() {
		return new Double(textValue());
	}
	private boolean booleanValue() {
		String value = textValue();
		if (value.equalsIgnoreCase("true"))
			return true;
		else
			return false;
	}
	private short shortValue() {
		return new Short(textValue());
	}
	
	public void setNotebookGuid(String g) {
		notebookGuid = g;
	}
	
	public String getErrorMessage() {
		return errorMessage;
	}
}
