/*
 * JBoss, Home of Professional Open Source.
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * Modified by
 * @author  Data Virtuality GmbH
 * @date    $Date$
 *  
 */
// https://issues.jboss.org/browse/TEIID-2235, 2661, 2178, 2297
// https://issues.redhat.com/browse/TEIID-4274
package org.teiid.metadata.index;

import java.io.IOException;

import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.MetadataRepository;
import org.teiid.translator.ExecutionFactory;
import org.teiid.translator.TranslatorException;

public class IndexMetadataRepository extends MetadataRepository {

	private IndexMetadataStore idxStore;
	
	public IndexMetadataRepository(IndexMetadataStore index) {
		this.idxStore = index;
	}

	@Override
	public void loadMetadata(MetadataFactory factory, ExecutionFactory executionFactory, Object connectionFactory)
			throws TranslatorException {
		try {
			if (this.idxStore.getSchema(factory.getName()) == null) {
				this.idxStore.load(factory.getName(), factory.getBuiltinDataTypes().values());
			}
			if (this.idxStore.getSchema(factory.getName()) == null) {
				throw new TranslatorException(RuntimeMetadataPlugin.Util.gs(RuntimeMetadataPlugin.Event.TEIID80004, factory.getName()));
			}
			factory.setSchema(this.idxStore.getSchema(factory.getName()));
		} catch (IOException e) {
			throw new TranslatorException(e);
		}
	}

	// uncomment after backporting TEIID-2449
	/*private void getProcedures(Schema model) {
		Map<Character, List<AbstractMetadataRecord>> entries = schemaEntries.get(model.getName());
		if (entries == null) {
			return;
		}

		List recs = entries.get(MetadataConstants.RECORD_TYPE.CALLABLE);
		if (recs == null) {
			return;
		}

		List<Procedure> records = recs;
		for (Procedure procedureRecord : records) {
			// get the parameter metadata info
			for (int i = 0; i < procedureRecord.getParameters().size(); i++) {
				ProcedureParameter paramRecord = (ProcedureParameter) this.getRecordByType(procedureRecord.getParameters().get(i).getUUID(), MetadataConstants.RECORD_TYPE.CALLABLE_PARAMETER);
				paramRecord.setDatatype((Datatype) getByType(MetadataConstants.RECORD_TYPE.DATATYPE).get(paramRecord.getDatatypeUUID()));
				procedureRecord.getParameters().set(i, paramRecord);
				paramRecord.setProcedure(procedureRecord);
			}

			ColumnSet<Procedure> result = procedureRecord.getResultSet();
			if(result != null) {
				ColumnSet<Procedure> resultRecord = (ColumnSet<Procedure>) getRecordByType(result.getUUID(), MetadataConstants.RECORD_TYPE.RESULT_SET, false);
				if (resultRecord != null) {
					resultRecord.setParent(procedureRecord);
					resultRecord.setName(RecordFactory.getShortName(resultRecord.getName()));
					loadColumnSetRecords(resultRecord, null);
					procedureRecord.setResultSet(resultRecord);
				}
				//it is ok to be null here.  it will happen when a
				//virtual stored procedure is created from a
				//physical stored procedure without a result set
				//TODO: find a better fix for this
			}

			if (procedureRecord.isFunction()) {
				FunctionParameter outputParam = null;
				List<FunctionParameter> args = new ArrayList<FunctionParameter>(procedureRecord.getParameters().size() - 1);
				boolean valid = true;
				for (ProcedureParameter param : procedureRecord.getParameters()) {
					FunctionParameter fp = new FunctionParameter();
					fp.setName(param.getName());
					fp.setDescription(param.getAnnotation());
					fp.setRuntimeType(param.getRuntimeType());
					fp.setDatatype(param.getDatatype(), true, param.getArrayDimensions());
					switch (param.getType()) {
						case ReturnValue:
							if (outputParam != null) {
								valid = false;
							}
							outputParam = fp;
							break;
						case In:
							args.add(fp);
							break;
						default:
							valid = false;
					}
				}
				if (valid && outputParam != null) {
					FunctionMethod function = new FunctionMethod(procedureRecord.getName(), procedureRecord.getAnnotation(), model.getName(), procedureRecord.isVirtual()?PushDown.CAN_PUSHDOWN:PushDown.MUST_PUSHDOWN,
							null, null, args, outputParam, false, Determinism.DETERMINISTIC);
					FunctionMethod.convertExtensionMetadata(procedureRecord, function);
					if (function.getInvocationMethod() != null) {
						function.setPushdown(PushDown.CAN_PUSHDOWN);
					}
					model.addFunction(function);
					continue;
				}
			}

			// if this is a virtual procedure get the procedure plan
			if(procedureRecord.isVirtual()) {
				TransformationRecordImpl transformRecord = (TransformationRecordImpl)getRecordByType(procedureRecord.getUUID(), MetadataConstants.RECORD_TYPE.PROC_TRANSFORM, false);
				if(transformRecord != null) {
					procedureRecord.setQueryPlan(transformRecord.getTransformation());
				}
			}
			model.addProcedure(procedureRecord);
		}
	}*/
}
