package org.csstudio.dct.model.persistence.internal;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Enumeration;
import java.util.Iterator;

import org.csstudio.dct.ExtensionPointUtil;
import org.csstudio.dct.metamodel.IDatabaseDefinition;
import org.csstudio.dct.metamodel.PromptGroup;
import org.csstudio.dct.metamodel.internal.Choice;
import org.csstudio.dct.metamodel.internal.DatabaseDefinition;
import org.csstudio.dct.metamodel.internal.FieldDefinition;
import org.csstudio.dct.metamodel.internal.MenuDefinition;
import org.csstudio.dct.metamodel.internal.RecordDefinition;
import org.csstudio.dct.model.internal.Project;
import org.csstudio.dct.model.persistence.IPersistenceService;
import org.csstudio.dct.model.visitors.RecordFunctionPropertiesVisitor;
import org.csstudio.platform.logging.CentralLogger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import com.cosylab.vdct.Console;
import com.cosylab.vdct.ConsoleInterface;
import com.cosylab.vdct.dbd.DBDData;
import com.cosylab.vdct.dbd.DBDFieldData;
import com.cosylab.vdct.dbd.DBDMenuData;
import com.cosylab.vdct.dbd.DBDRecordData;
import com.cosylab.vdct.dbd.DBDResolver;

/**
 * Default persistence service implementation.
 * 
 * @author Sven Wende
 * 
 */
public final class PersistenceService implements IPersistenceService {
	/**
	 *{@inheritDoc}
	 */
	public void saveProject(IFile file, Project project) throws Exception {
		XMLOutputter outp = new XMLOutputter();

		ProjectToXml projectToXml = new ProjectToXml(project);

		Document doc = projectToXml.createDocument();

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		outp.output(doc, bos);
		file.setContents(new ByteArrayInputStream(bos.toByteArray()), true, false, new NullProgressMonitor());
	}

	/**
	 *{@inheritDoc}
	 */
	public Project loadProject(IFile file) throws Exception {
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(file.getContents());

		XmlToProject xmlToProject = new XmlToProject(doc);

		Project p = xmlToProject.getProject();

		p.accept(new RecordFunctionPropertiesVisitor(ExtensionPointUtil.getRecordAttributes()));

		return p;
	}

	/**
	 *{@inheritDoc}
	 */
	public IDatabaseDefinition loadDatabaseDefinition(String path) {
		IDatabaseDefinition result = null;

		if (path != null && path.length() > 0) {

			// .. file system search
			File file = new File(path);

			if (file.exists()) {
				result = doLoadDatabaseDefinition(file.getAbsolutePath());
			}

			// .. workspace search
			if (result == null) {
				IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));

				if (workspaceFile != null && workspaceFile.getLocation() != null) {
					result = doLoadDatabaseDefinition(workspaceFile.getLocation().toOSString());
				}
			}
		}

		return result;
	}

	/**
	 * Loads a database definition from a dbd file using an API of the VDCT
	 * software.
	 * 
	 * @param path
	 *            the absolute path to the dbd file
	 * @return the database definition (meta model)
	 */
	@SuppressWarnings( { "unchecked" })
	private IDatabaseDefinition doLoadDatabaseDefinition(String path) {
		DatabaseDefinition databaseDefinition = new DatabaseDefinition("1.0");

		// .. redirect the VDCT console
		Console.setInstance(new ConsoleInterface() {

			public void flush() {

			}

			public void print(String text) {
				CentralLogger.getInstance().info(null, text);
			}

			public void println() {
				CentralLogger.getInstance().info(null, "\r\n");
			}

			public void println(String text) {
				CentralLogger.getInstance().info(null, text);
			}

			public void println(Throwable thr) {
				CentralLogger.getInstance().error(null, thr);
			}

			public void silent(String text) {
				CentralLogger.getInstance().debug(null, text);
			}

		});

		// .. use the VDCT parser
		DBDData data = new DBDData();
		DBDResolver.resolveDBD(data, path);

		// .. transform the VDCT dbd model to our CSS-DCTs meta model

		// .. menus

		// .. records

		Enumeration<String> it = data.getRecordNames();
		while (it.hasMoreElements()) {
			String n = it.nextElement();
			DBDRecordData recordData = data.getDBDRecordData(n);

			RecordDefinition recordDefinition = new RecordDefinition(n);
			databaseDefinition.addRecordDefinition(recordDefinition);

			Iterator<DBDFieldData> it2 = recordData.getFieldsV().iterator();

			while (it2.hasNext()) {
				DBDFieldData fieldData = it2.next();
				String fieldName = fieldData.getName();
				CentralLogger.getInstance().info(null, fieldName);

				FieldDefinition fieldDefinition = new FieldDefinition(fieldName, DBDResolver.getFieldType(fieldData.getField_type()));

				// .. prompt group
				fieldDefinition.setPromptGroup(PromptGroup.findByType(fieldData.getGUI_type()));

				// .. prompt
				fieldDefinition.setPrompt(fieldData.getPrompt_value());

				// .. menu
				String menuName = fieldData.getMenu_name();

				if (menuName != null && menuName.length() > 0) {
					DBDMenuData menuData = data.getDBDMenuData(menuName);

					if (menuData != null) {
						MenuDefinition menuDefinition = new MenuDefinition(menuName);

						for (Choice c : menuData.getChoicesForCssDct()) {
							menuDefinition.addChoice(c);
						}

						fieldDefinition.setMenuDefinition(menuDefinition);
					}
				}

				// .. initial value
				fieldDefinition.setInitial(fieldData.getInit_value());

				recordDefinition.addFieldDefinition(fieldDefinition);
			}
		}

		return databaseDefinition;
	}
}

@@ -1115,24 +1115,55 @@
 SAXBuilder;%0A
+import org.jdom.output.Format;%0A
 import org.j
@@ -1724,16 +1724,101 @@
 ption %7B%0A
+%09%09Format format = Format.getPrettyFormat();%0A//%09%09format.setEncoding(%22ISO-8859-1%22);%0A%09%09%0A
 %09%09XMLOut
@@ -1851,16 +1851,41 @@
 tter();%0A
+%09%09outp.setFormat(format);
 %0A%09%09Proje

Set the XMLOutputter the Pretty format for line breaks.