Skip to content

Commit

Permalink
Implement local version of position() and last()
Browse files Browse the repository at this point in the history
  • Loading branch information
ghislainfourny committed Nov 14, 2019
1 parent 6402790 commit e6ced9c
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea/
target/
*.iml
/bin/
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Stefan Irimescu, Can Berker Cikis
*
*/


package sparksoniq.exceptions;

import sparksoniq.exceptions.codes.ErrorCodes;
import sparksoniq.jsoniq.compiler.translator.metadata.ExpressionMetadata;
import sparksoniq.jsoniq.runtime.metadata.IteratorMetadata;

public class AbsentPartOfDynamicContextException extends SparksoniqRuntimeException {

private static final long serialVersionUID = 1L;

public AbsentPartOfDynamicContextException(String message, IteratorMetadata iteratorMetadata) {
super(message, ErrorCodes.AbsentPartOfDynamicContextCode, iteratorMetadata.getExpressionMetadata());
}
}
1 change: 1 addition & 0 deletions src/main/java/sparksoniq/exceptions/codes/ErrorCodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class ErrorCodes {
public static final String UnimplementedErrorCode = "SPRKIQ0002";


public static final String AbsentPartOfDynamicContextCode = "XPDY0002";
public static final String DynamicTypeTreatErrorCode = "XPDY0050";
public static final String RuntimeExceptionErrorCode = "XPDY0130";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import sparksoniq.jsoniq.runtime.iterator.functions.binaries.HexBinaryFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.booleans.BooleanFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.io.JsonDocFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.context.PositionFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.context.LastFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.datetime.DateFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.datetime.DateTimeFunctionIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.datetime.TimeFunctionIterator;
Expand Down Expand Up @@ -131,6 +133,9 @@ public class Functions {
userDefinedFunctions = new HashMap<>();
builtInFunctions = new HashMap<>();

builtInFunctions.put(new FunctionIdentifier(POSITION, 0), PositionFunctionIterator.class);
builtInFunctions.put(new FunctionIdentifier(LAST, 0), LastFunctionIterator.class);

builtInFunctions.put(new FunctionIdentifier(JSON_FILE, 1), ParseJsonFunctionIterator.class);
builtInFunctions.put(new FunctionIdentifier(JSON_FILE, 2), ParseJsonFunctionIterator.class);
builtInFunctions.put(new FunctionIdentifier(JSON_DOC, 1), JsonDocFunctionIterator.class);
Expand Down Expand Up @@ -310,6 +315,14 @@ public static FunctionItem getUserDefinedFunction(FunctionIdentifier identifier,
}

public static class FunctionNames {
/**
* function that returns the context position
*/
public static final String POSITION = "position";
/**
* function that returns the context size
*/
public static final String LAST = "last";

/**
* function that parses a JSON lines file
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Stefan Irimescu, Can Berker Cikis
*
*/

package sparksoniq.jsoniq.runtime.iterator.functions.context;

import sparksoniq.exceptions.AbsentPartOfDynamicContextException;
import sparksoniq.jsoniq.item.ItemFactory;
import sparksoniq.jsoniq.runtime.iterator.RuntimeIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.base.LocalFunctionCallIterator;
import sparksoniq.jsoniq.runtime.metadata.IteratorMetadata;
import sparksoniq.semantics.DynamicContext;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.rumbledb.api.Item;

public class LastFunctionIterator extends LocalFunctionCallIterator {


private static final long serialVersionUID = 1L;

public LastFunctionIterator(List<RuntimeIterator> arguments, IteratorMetadata iteratorMetadata) {
super(arguments, iteratorMetadata);
}

@Override
public void open(DynamicContext context) {
super.open(context);
this._hasNext = true;
}

@Override
public Item next() {
if (this._hasNext) {
this._hasNext = false;
long last = _currentDynamicContext.getLast();
if(last == -1)
{
throw new AbsentPartOfDynamicContextException("Context indefined (last) ", getMetadata());
}
if(last < Integer.MAX_VALUE)
{
return ItemFactory.getInstance().createIntegerItem((int)last);
} else {
return ItemFactory.getInstance().createDecimalItem(new BigDecimal(last));
}
}
return null;
}

public Map<String, DynamicContext.VariableDependency> getVariableDependencies() {
Map<String, DynamicContext.VariableDependency> result = new TreeMap<String, DynamicContext.VariableDependency>();
result.put("$last", DynamicContext.VariableDependency.FULL);
return result;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Stefan Irimescu, Can Berker Cikis
*
*/

package sparksoniq.jsoniq.runtime.iterator.functions.context;

import sparksoniq.exceptions.AbsentPartOfDynamicContextException;
import sparksoniq.jsoniq.item.ItemFactory;
import sparksoniq.jsoniq.runtime.iterator.RuntimeIterator;
import sparksoniq.jsoniq.runtime.iterator.functions.base.LocalFunctionCallIterator;
import sparksoniq.jsoniq.runtime.metadata.IteratorMetadata;
import sparksoniq.semantics.DynamicContext;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.rumbledb.api.Item;

public class PositionFunctionIterator extends LocalFunctionCallIterator {


private static final long serialVersionUID = 1L;

public PositionFunctionIterator(List<RuntimeIterator> arguments, IteratorMetadata iteratorMetadata) {
super(arguments, iteratorMetadata);
}

@Override
public void open(DynamicContext context) {
super.open(context);
this._hasNext = true;
}

@Override
public Item next() {
if (this._hasNext) {
this._hasNext = false;
long position = _currentDynamicContext.getPosition();
if(position == -1)
{
throw new AbsentPartOfDynamicContextException("Context indefined (position) ", getMetadata());
}
if(position < Integer.MAX_VALUE)
{
return ItemFactory.getInstance().createIntegerItem((int)position);
} else {
return ItemFactory.getInstance().createDecimalItem(new BigDecimal(position));
}
}
return null;
}

public Map<String, DynamicContext.VariableDependency> getVariableDependencies() {
Map<String, DynamicContext.VariableDependency> result = new TreeMap<String, DynamicContext.VariableDependency>();
result.put("$position", DynamicContext.VariableDependency.FULL);
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ public class PredicateIterator extends HybridRuntimeIterator {
private RuntimeIterator _iterator;
private RuntimeIterator _filter;
private Item _nextResult;
private long _position;
private boolean _mustMaintainPosition;
private DynamicContext _filterDynamicContext;


public PredicateIterator(RuntimeIterator sequence, RuntimeIterator filterExpression, IteratorMetadata iteratorMetadata) {
super(Arrays.asList(sequence, filterExpression), iteratorMetadata);
_iterator = sequence;
_filter = filterExpression;
_filterDynamicContext = null;
}

@Override
Expand All @@ -68,7 +72,18 @@ protected boolean hasNextLocal() {

@Override
protected void resetLocal(DynamicContext context) {
_iterator.reset(_currentDynamicContext);
_iterator.close();
_filterDynamicContext = new DynamicContext(_currentDynamicContext);
if(_filter.getVariableDependencies().containsKey("$last"))
{
setLast();
}
if(_filter.getVariableDependencies().containsKey("$position"))
{
_position = 0;
_mustMaintainPosition = true;
}
_iterator.open(_currentDynamicContext);
setNextResult();
}

Expand All @@ -82,9 +97,31 @@ protected void openLocal() {
if (this._children.size() < 2) {
throw new SparksoniqRuntimeException("Invalid Predicate! Must initialize filter before calling next");
}
_filterDynamicContext = new DynamicContext(_currentDynamicContext);
if(_filter.getVariableDependencies().containsKey("$last"))
{
setLast();
}
if(_filter.getVariableDependencies().containsKey("$position"))
{
_position = 0;
_mustMaintainPosition = true;
}
_iterator.open(_currentDynamicContext);
setNextResult();
}

private void setLast() {
long last = 0;
_iterator.open(_currentDynamicContext);
while(_iterator.hasNext())
{
_iterator.next();
++last;
}
_iterator.close();
_filterDynamicContext.setLast(last);
}

private void setNextResult() {
_nextResult = null;
Expand All @@ -93,9 +130,11 @@ private void setNextResult() {
Item item = _iterator.next();
List<Item> currentItems = new ArrayList<>();
currentItems.add(item);
_currentDynamicContext.addVariableValue("$$", currentItems);
_filterDynamicContext.addVariableValue("$$", currentItems);
if(_mustMaintainPosition)
_filterDynamicContext.setPosition(++_position);

_filter.open(_currentDynamicContext);
_filter.open(_filterDynamicContext);
Item fil = null;
if (_filter.hasNext()) {
fil = _filter.next();
Expand All @@ -118,7 +157,7 @@ private void setNextResult() {
}
_filter.close();
}
_currentDynamicContext.removeVariable("$$");
_filterDynamicContext.removeVariable("$$");

if (_nextResult == null) {
this._hasNext = false;
Expand Down
Loading

0 comments on commit e6ced9c

Please sign in to comment.