Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Union operator #8

Merged
merged 16 commits into from
Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions java-vtl-model/src/main/java/kohl/hadrien/AbstractComponent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package kohl.hadrien;

import com.google.common.base.MoreObjects;

import java.util.Objects;

/**
* Abstract component implementation.
*/
public abstract class AbstractComponent<T> implements Component<T> {

@Override
public String toString() {
return MoreObjects.toStringHelper(type())
.add(name(), get().toString())
.toString();
}

@Override
public int hashCode() {
return Objects.hash(
name(),
type(),
get()
);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Component that = (Component) o;
return Objects.equals(that.name(), name())
&& Objects.equals(that.type(), type())
&& Objects.equals(that.get(), get());
}
}
86 changes: 65 additions & 21 deletions java-vtl-model/src/main/java/kohl/hadrien/DataStructure.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,24 @@
import java.util.Set;
import java.util.function.BiFunction;

import static com.google.common.base.Preconditions.checkArgument;

/**
* Datastructure of a {@link Dataset}.
*
* In addition to defining the type and roles of variable in the data sets, the data structure decouples
* the creation of the {@link kohl.hadrien.Dataset.Tuple}.
* Data structure of a {@link Dataset}.
* <p>
* The data structure defines the role and type of the columns of a data set and
* serves as a {@link Component}'s factory.
*/
public abstract class DataStructure {

/**
* Creates a new data structure.
*/
public static DataStructure of(BiFunction<String, Object, Component> converter,
public static DataStructure of(BiFunction<Object, Class<?>, ?> converter,
String name1, Class<? extends Component> role1, Class<?> type1) {
return new DataStructure() {
@Override
public BiFunction<String, Object, Component> converter() {
public BiFunction<Object, Class<?>, ?> converter() {
return converter;
}

Expand All @@ -68,12 +70,12 @@ public Set<String> names() {
/**
* Creates a new data structure.
*/
public static DataStructure of(BiFunction<String, Object, Component> converter,
public static DataStructure of(BiFunction<Object, Class<?>, ?> converter,
String name1, Class<? extends Component> role1, Class<?> type1,
String name2, Class<? extends Component> role2, Class<?> type2) {
return new DataStructure() {
@Override
public BiFunction<String, Object, Component> converter() {
public BiFunction<Object, Class<?>, ?> converter() {
return converter;
}

Expand All @@ -97,13 +99,13 @@ public Set<String> names() {
/**
* Creates a new data structure.
*/
public static DataStructure of(BiFunction<String, Object, Component> converter,
public static DataStructure of(BiFunction<Object, Class<?>, ?> converter,
String name1, Class<? extends Component> role1, Class<?> type1,
String name2, Class<? extends Component> role2, Class<?> type2,
String name3, Class<? extends Component> role3, Class<?> type3) {
return new DataStructure() {
@Override
public BiFunction<String, Object, Component> converter() {
public BiFunction<Object, Class<?>, ?> converter() {
return converter;
}

Expand All @@ -127,14 +129,14 @@ public Set<String> names() {
/**
* Creates a new data structure.
*/
public static DataStructure of(BiFunction<String, Object, Component> converter,
public static DataStructure of(BiFunction<Object, Class<?>, ?> converter,
String name1, Class<? extends Component> role1, Class<?> type1,
String name2, Class<? extends Component> role2, Class<?> type2,
String name3, Class<? extends Component> role3, Class<?> type3,
String name4, Class<? extends Component> role4, Class<?> type4) {
return new DataStructure() {
@Override
public BiFunction<String, Object, Component> converter() {
public BiFunction<Object, Class<?>, ?> converter() {
return converter;
}

Expand All @@ -155,15 +157,57 @@ public Set<String> names() {
};
}

public abstract BiFunction<String, Object, Component> converter();

public Dataset.Tuple wrap(Map<String, Object> objects) {
public abstract BiFunction<Object, Class<?>, ?> converter();

/**
* Creates a new {@link Component} for the given column and value.
*
* @param name the name of the column.
* @param value the value of the resulting component.
* @return a component
*/
public Component wrap(String name, Object value) {
checkArgument(types().containsKey(name) && roles().containsKey(name),
"could not find %s in data structure %s", name, this);

return new AbstractComponent() {
@Override
public String name() {
return name;
}

@Override
public Class<?> type() {
return types().get(name);
}

@Override
public Class<? extends Component> role() {
return roles().get(name);
}

@Override
public Object get() {
return converter().apply(value, type());
}
};
}

/**
* Creates a new {@link kohl.hadrien.Dataset.Tuple} for the given names and values.
* <p>
* This method uses the {@link #wrap(String, Object)} method to convert each value and returns
* a {@link kohl.hadrien.Dataset.Tuple}.
*
* @param map a map of name and values
* @return the corresponding tuple (row)
*/
public Dataset.Tuple wrap(Map<String, Object> map) {

List<Component> components = Lists.newArrayList();
for (Map.Entry<String, Object> entry : objects.entrySet()) {
Component component = converter().apply(entry.getKey(), entry.getValue());
components.add(component);
}
for (Map.Entry<String, Object> entry : map.entrySet())
components.add(wrap(entry.getKey(), entry.getValue()));

return Dataset.Tuple.create(components);

Expand All @@ -186,13 +230,13 @@ public abstract class ForwardingDataStructure extends DataStructure {
protected abstract DataStructure delegate();

@Override
public BiFunction<String, Object, Component> converter() {
public BiFunction<Object, Class<?>, ?> converter() {
return delegate().converter();
}

@Override
public Dataset.Tuple wrap(Map<String, Object> objects) {
return delegate().wrap(objects);
public Dataset.Tuple wrap(Map<String, Object> map) {
return delegate().wrap(map);
}

@Override
Expand Down
49 changes: 36 additions & 13 deletions java-vtl-model/src/main/java/kohl/hadrien/Dataset.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,56 @@
import com.codepoetics.protonpack.Streamable;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ForwardingList;
import com.google.common.collect.Sets;

import java.util.*;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
* A data structure that allows relational operations.
*/
public interface Dataset extends Streamable<Dataset.Tuple> {

Set<List<Identifier>> cartesian();


/**
* Returns the data structure of the DataSet.
*/
DataStructure getDataStructure();

static Comparator<Tuple> comparatorFor(Class<? extends Component>... roles) {
Set<Class<? extends Component>> rolesHash = Sets.newHashSet(roles);
return new Comparator<Tuple>() {
@Override
public int compare(Tuple li, Tuple ri) {
Comparator comparator = Comparator.naturalOrder();

Map<String, Object> lm = li.stream().filter(component -> rolesHash.contains(component.role()))
.collect(Collectors.toMap(
Component::name,
Component::get
));

Map<String, Object> rm = ri.stream().filter(component -> rolesHash.contains(component.role()))
.collect(Collectors.toMap(
Component::name,
Component::get
));

checkArgument(lm.keySet().equals(rm.keySet()));
int i = 0;
for (String key : lm.keySet()) {
i = comparator.compare(lm.get(key), rm.get(key));
if (i != 0)
return i;
}
return i;

}
};
}

interface Tuple extends List<Component>, Comparable<Tuple> {

static Tuple create(List<Component> components) {
Expand Down Expand Up @@ -91,8 +122,8 @@ public Object get() {
@Override
public String toString() {
return MoreObjects.toStringHelper(role())
.add("name", name())
.addValue(get()).toString();
.add(name(), get().toString())
.toString();
}
})
.collect(Collectors.toList());
Expand Down Expand Up @@ -194,14 +225,6 @@ public int hashCode() {
return ids().hashCode();
}

@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || getClass() != other.getClass())
return false;
return this.ids().equals(((Tuple) other).ids());
}

@Override
public Tuple combine(Tuple tuple) {
Expand Down
3 changes: 0 additions & 3 deletions java-vtl-model/src/main/java/kohl/hadrien/Identifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,5 @@
* #L%
*/

/**
* Created by hadrien on 07/09/16.
*/
public interface Identifier<T extends Comparable> extends Component<T> {
}
11 changes: 11 additions & 0 deletions java-vtl-parser/src/main/antlr4/imports/Relational.g4
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
grammar Relational;

relationalExpression : unionExpression ;

unionExpression : 'union' '(' datasetExpression (',' datasetExpression )* ')' ;

datasetExpression : 'datasetExpr' NUM+;


NUM : '0'..'9' ;
WS : [ \t\n\t] -> skip ;
9 changes: 5 additions & 4 deletions java-vtl-parser/src/main/antlr4/kohl/hadrien/VTL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
grammar VTL;

import Atoms, Clauses, Conditional;
import Atoms, Clauses, Conditional, Relational;

start : statement+ EOF;

Expand All @@ -30,9 +30,10 @@ exprMember : datasetExpression ('#' componentID)? ;

/* Expressions */
datasetExpression : <assoc=right>datasetExpression clauseExpression #withClause
| getExpression #withGet
| putExpression #withPut
| exprAtom #withAtom
| relationalExpression #withRelational
| getExpression #withGet
| putExpression #withPut
| exprAtom #withAtom
;

componentID : IDENTIFIER;
Expand Down
Loading