//package org.olap4j.driver.olap4ld.linkeddata;
//
//
///**
// * This visitor creates a physical query plan. It is different from
// * OlapDrillAcross2SparqlSesameVisitor and Olap2SparqlSesameVisitor that only
// * use two Iterators, Olap2SparqlAlgorithmSesameIterator and
// * OlapDrillAcross2SparqlSesameIterator. They implement the Drill-Across
// * algorithm and the OLAP-to-SPARQL algorithm.
// *
// * Olap2SparqlSesameDerivedDatasetVisitor uses for every logical olap operator a
// * separate physical olap iterator. Here, the repo also needs to be pre-filled with
// * data cubes, yet, every iterator creates a new derived data cube.
// *
// * @author benedikt
// */
//public class Olap2SparqlSesameDerivedDatasetVisitor implements
// LogicalOlapOperatorQueryPlanVisitor {
// // the new root node
// PhysicalOlapIterator _root;
//
// // For the moment, we know the engine
// private EmbeddedSesameEngine engine;
//
// /**
// *
// * * Design decisions The LogicalOperators only get as input a cube and the
// * parameters, but not specifically the metadata of the cube.
// *
// * The PhysicalIterators get as input another iterator and the parameters,
// * but also the metadata of the iterator. I create PhysicalIterators for
// * metadata, they get as input the repo and the parameters (restrictions).
// * Every LogicalOperator could be wrapped, get as input the identifier of a
// * cube and the parameters and return a new identifier.
// *
// * Mioeur2eur is another LogicalOperator that could get wrapped, get as
// * input the identifier of a cube and the parameters and return a new
// * identifier. Mioeur2eur would also include PhysicalIterators. The
// * Mioeur2eur iterator would get as input another iterator,
// * BaseCubeIterator, and return the conversion. Example:
// * http://olap4ld.googlecode.com/dic/aggreg95#00;
// * http://olap4ld.googlecode.com/dic/geo#US;
// * http://olap4ld.googlecode.com/dic/indic_na#VI_PPS_EU28_HAB; 2012; 149;
// *
// */
// public Olap2SparqlSesameDerivedDatasetVisitor(EmbeddedSesameEngine engine) {
// this.engine = engine;
// }
//
// /**
// * After iteration, create new root. I want to have simple SPARQL query +
// * load RDF to store.
// */
// public Object getNewRoot() {
//
// return _root;
//
// // Try to normally evaluate all operators apart from drill-across
//
// // // We collect necessary parts of the SPARQL query.
// // String selectClause = " ";
// // String whereClause = " ";
// // String groupByClause = " group by ";
// // String orderByClause = " order by ";
// // if (_root instanceof DrillAcrossSparqlIterator) {
// // return _root;
// // } else {
// // List<List<Node[]>> metadata = (ArrayList<List<Node[]>>) _root
// // .next();
// // List<Node[]> cubes = metadata.get(0);
// // List<Node[]> measures = metadata.get(1);
// // List<Node[]> dimensions = metadata.get(2);
// // List<Node[]> hierarchies = metadata.get(3);
// // List<Node[]> levels = metadata.get(4);
// // List<Node[]> members = metadata.get(5);
// //
// // // BaseCube
// //
// // Map<String, Integer> map = Olap4ldLinkedDataUtil
// // .getNodeResultFields(cubes.get(0));
// //
// // // Cube gives us the URI of the dataset that we want to resolve
// // String ds = cubes.get(1)[map.get("CUBE_NAME")].toString();
// //
// // whereClause += "?obs qb:dataSet" + ds + ". ";
// //
// // // Projections
// // List<Node[]> projections = measures;
// //
// // // Now, for each measure, we create a measure value column.
// // // Any measure should be contained only once, unless calculated
// // // measures
// // HashMap<Integer, Boolean> measureMap = new HashMap<Integer,
// // Boolean>();
// // map = Olap4ldLinkedDataUtil.getNodeResultFields(projections.get(0));
// // boolean first = true;
// //
// // for (Node[] measure : projections) {
// //
// // if (first) {
// // first = false;
// // continue;
// // }
// //
// // // For formulas, this is different
// // // XXX: Needs to be put before creating the Logical Olap
// // // Operator
// // // Tree
// // // Will probably not work since MEASURE_AGGREGATOR
// // if (measure[map.get("?MEASURE_AGGREGATOR")].toString().equals(
// // "http://purl.org/olap#calculated")) {
// //
// // /*
// // * For now, hard coded. Here, I also partly evaluate a query
// // * string, thus, I could do the same with filters.
// // */
// // // Measure measure1 = (Measure) ((MemberNode) ((CallNode)
// // // measure
// // // .getExpression()).getArgList().get(0)).getMember();
// // // Measure measure2 = (Measure) ((MemberNode) ((CallNode)
// // // measure
// // // .getExpression()).getArgList().get(1)).getMember();
// // //
// // // String operatorName = ((CallNode)
// // // measure.getExpression())
// // // .getOperatorName();
// //
// // // Measure
// // // Measure property has aggregator attached to it at the
// // // end,
// // // e.g., "AVG".
// // // String measureProperty1 = Olap4ldLinkedDataUtil
// // // .convertMDXtoURI(measure1.getUniqueName()).replace(
// // // "AGGFUNC" + measure.getAggregator().name(), "");
// // // We do not encode the aggregation function in the measure,
// // // any
// // // more.
// // // String measurePropertyVariable1 =
// // // makeUriToParameter(measure1
// // // .getUniqueName());
// // //
// // // String measureProperty2 = Olap4ldLinkedDataUtil
// // // .convertMDXtoURI(measure2.getUniqueName()).replace(
// // // "AGGFUNC" + measure.getAggregator().name(), "");
// // // String measurePropertyVariable2 =
// // // makeUriToParameter(measure2
// // // .getUniqueName());
// //
// // // We take the aggregator from the measure
// // // selectClause += " " + measure1.getAggregator().name() +
// // // "(?"
// // // + measurePropertyVariable1 + " " + operatorName + " "
// // // + "?" + measurePropertyVariable2 + ")";
// // //
// // // // I have to select them only, if we haven't inserted any
// // // // before.
// // // if (!measureMap.containsKey(measureProperty1.hashCode()))
// // // {
// // // whereClause += " ?obs <" + measureProperty1 + "> ?"
// // // + measurePropertyVariable1 + ". ";
// // // measureMap.put(measureProperty1.hashCode(), true);
// // // }
// // // if (!measureMap.containsKey(measureProperty2.hashCode()))
// // // {
// // // whereClause += " ?obs <" + measureProperty2 + "> ?"
// // // + measurePropertyVariable2 + ". ";
// // // measureMap.put(measureProperty2.hashCode(), true);
// // // }
// //
// // } else {
// //
// // // As always, remove Aggregation Function from Measure Name
// // String measureProperty = measure[map
// // .get("?MEASURE_UNIQUE_NAME")].toString().replace(
// // "AGGFUNC"
// // + measure[map.get("?MEASURE_AGGREGATOR")]
// // .toString()
// // .replace("http://purl.org/olap#",
// // ""), "");
// //
// // // We also remove aggregation function from Measure Property
// // // Variable so
// // // that the same property is not selected twice.
// // String measurePropertyVariable = makeUriToParameter(measure[map
// // .get("?MEASURE_UNIQUE_NAME")].toString().replace(
// // "AGGFUNC"
// // + measure[map.get("?MEASURE_AGGREGATOR")]
// // .toString()
// // .replace("http://purl.org/olap#",
// // ""), ""));
// //
// // // Unique name for variable
// // String uniqueMeasurePropertyVariable = makeUriToParameter(measure[map
// // .get("?MEASURE_UNIQUE_NAME")].toString());
// //
// // // We take the aggregator from the measure
// // // Since we use OPTIONAL, there might be empty columns,
// // // which is why we need
// // // to convert them to decimal.
// // selectClause += " ("
// // + measure[map.get("?MEASURE_AGGREGATOR")]
// // .toString().replace(
// // "http://purl.org/olap#", "") + "(?"
// // + measurePropertyVariable + ") as ?"
// // + uniqueMeasurePropertyVariable + ")";
// //
// // // According to spec, every measure needs to be set for
// // // every
// // // observation only once
// // if (!measureMap.containsKey(measureProperty.hashCode())) {
// // whereClause += "?obs <" + measureProperty + "> ?"
// // + measurePropertyVariable + ".";
// // measureMap.put(measureProperty.hashCode(), true);
// // }
// // }
// // }
// //
// // }
// //
// // // Dice
// // // Not possible currently
// //
// // // Slice
// //
// // // Rollup
// //
// // // Initialise triple store with dataset URI
// //
// // // Query triple store with SPARQL query
// // // Now that we consider DSD in queries, we need to consider DSD
// // // locations
// // String query = Olap4ldLinkedDataUtil.getStandardPrefixes() +
// // "select "
// // + selectClause + askForFrom(false) + askForFrom(true)
// // + "where { " + whereClause + "}" + groupByClause
// // + orderByClause;
// //
// // // Currently, we should have retrieved the data, already, therefore,
// // we
// // // only have one node.
// // _root = new SparqlSesameIterator(repo, query);
// //
// // return _root;
// }
//
// @Override
// public void visit(DrillAcrossOp op) throws QueryException {
//
// throw new UnsupportedOperationException(
// "visit(DrillAcrossOp op) not implemented!");
//
//// DrillAcrossOp so = (DrillAcrossOp) op;
////
//// // Most probable, the _root will be null
//// so.inputop1.accept(this);
//// PhysicalOlapIterator root1 = _root;
////
//// so.inputop2.accept(this);
//// PhysicalOlapIterator root2 = _root;
////
//// DrillAcrossSparqlDerivedDatasetIterator resultiterator = new DrillAcrossSparqlDerivedDatasetIterator(
//// root1, root2);
////
//// _root = resultiterator;
// }
//
// @Override
// public void visit(RollupOp op) throws QueryException {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public void visit(SliceOp op) throws QueryException {
//
// // TODO Auto-generated method stub
// throw new UnsupportedOperationException(
// "visit(SliceOp op) not implemented!");
//
//// SliceOp so = (SliceOp) op;
////
//// so.inputOp.accept(this);
////
//// SliceSparqlDerivedDatasetIterator slicecube = new SliceSparqlDerivedDatasetIterator(engine, _root,
//// so.slicedDimensions);
////
//// _root = slicecube;
// }
//
// @Override
// public void visit(DiceOp op) throws QueryException {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public void visit(ProjectionOp op) throws QueryException {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public void visit(BaseCubeOp op) throws QueryException {
// BaseCubeOp so = (BaseCubeOp) op;
//
// // TODO One possibility is it to directly create the tree
// // Add physical operator that retrieves data from URI and stores it
// // in triple store
// // ExecIterator bi = null;
// // _root = bi;
//
// // We do not need to change those metadata.
//
// BaseCubeSparqlDerivedDatasetIterator basecube = new BaseCubeSparqlDerivedDatasetIterator(engine, so.dataseturi);
// _root = basecube;
// }
//
// @Override
// public void visit(ConvertCubeOp op) throws QueryException {
// ConvertCubeOp so = (ConvertCubeOp) op;
//
// ConvertSparqlDerivedDatasetIterator convertcontextcube;
// if (so.inputOp2 == null) {
//
// so.inputOp1.accept(this);
// PhysicalOlapIterator root = _root;
// convertcontextcube = new ConvertSparqlDerivedDatasetIterator(engine, root,
// null, so.conversioncorrespondence, so.domainUri);
// } else if (so.inputOp1 == so.inputOp2) {
// // If both operators are the same, we can reuse the iterator.
// // Unfortunately, this does not work for further nested equal
// // operators.
// // If inside a logical olap query plan the same function is run on
// // the same dataset, we
// // still have a problem that it is run twice. we could have a
// // hashmap storing
// // previous operators and reusing them if needed.
// so.inputOp1.accept(this);
// PhysicalOlapIterator root = _root;
// convertcontextcube = new ConvertSparqlDerivedDatasetIterator(engine, root,
// root, so.conversioncorrespondence, so.domainUri);
// } else {
// so.inputOp1.accept(this);
// PhysicalOlapIterator root1 = _root;
// so.inputOp2.accept(this);
// PhysicalOlapIterator root2 = _root;
//
// convertcontextcube = new ConvertSparqlDerivedDatasetIterator(engine, root1,
// root2, so.conversioncorrespondence, so.domainUri);
// }
//
// _root = convertcontextcube;
// }
//
// @Override
// public void visit(Object op) throws QueryException {
// // TODO Auto-generated method stub
// throw new UnsupportedOperationException(
// "visit(Object op) not implemented!");
// }
//}