Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2013-2019 Cinchapi Inc.
*
* Licensed 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.
*/
package com.cinchapi.concourse.lang.sort;

/**
* The base class for a Sort Order state that can be transformed into a complete
* and well-formed {@link Order}.
*/
public abstract class BuildableOrderState extends OrderState {

/**
* Construct a new instance.
*
* @param order
*/
protected BuildableOrderState(Order order) {
super(order);
}

/**
* Build and return the {@link Order}.
*
* @return the built Order
*/
public final Order build() {
order.close();
return order;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2013-2019 Cinchapi Inc.
*
* Licensed 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.
*/
package com.cinchapi.concourse.lang.sort;

/**
* Sort directions.
*
* @author Jeff Nelson
*/
enum Direction {

ASCENDING(1), DESCENDING(-1);

/**
* Return the default {@link Direction}.
*
* @return the default
*/
static Direction $default() {
return Direction.ASCENDING;
}

/**
* The coefficient is multiplied by the result of a {@link Comparator} to
* sort elements in forward or reverse order.
*/
private final int coefficient;

/**
* Construct a new instance.
*
* @param coefficient
*/
Direction(int coefficient) {
this.coefficient = coefficient;
}

/**
* Return the coefficient associated with this {@link Direction}.
*
* @return the coefficient
*/
public int coefficient() {
return coefficient;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2013-2019 Cinchapi Inc.
*
* Licensed 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.
*/
package com.cinchapi.concourse.lang.sort;

import java.util.LinkedHashMap;
import java.util.Objects;

import javax.annotation.Nullable;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

/**
* {@link Order} encapsulates the semantics of a result set sorting. Any given
* time, objects of this class can exist in one of two modes: {@code building}
* or {@code built}. When an Order is
* {@code built}, it is guaranteed to represent a fully and well formed sort
* order that can be processed. On the other hand, when a Order is
* {@code building} it is in an incomplete state.
* <p>
* This class is the public interface to Order construction. It is meant to
* be used in a chained manner, where the caller initially calls
* {@link Order#by} and continues to construct the Order using the
* options available from each subsequently returned state.
* </p>
*
*/
public final class Order {

/**
* Start building a new {@link Order}.
*
* @return the Order builder
*/
public static OrderByState by(String key) {
Order order = new Order();
return new OrderByState(order, key, Direction.$default());
}

/**
* A mapping from each key to direction ordinal (e.g. 1 for ASC and -1 for
* DESC) in the constructed {@link Order}.
*/
@VisibleForTesting
final LinkedHashMap<String, Integer> spec;

/**
* The last key that was {@link #add(String, Direction) added}.
*/
@Nullable
protected String lastKey;

/**
* A flag that indicates whether this {@link Order} has been built.
*/
private boolean built = false;

/**
* Construct a new instance.
*/
private Order() {
this.spec = Maps.newLinkedHashMap();
}

@Override
public boolean equals(Object obj) {
if(obj instanceof Order) {
return Objects.equals(spec, ((Order) obj).spec);
}
else {
return false;
}
}

@Override
public int hashCode() {
return spec.hashCode();
}

/**
* Mark this {@link Order} as {@code built}.
*/
void close() {
built = !built ? true : built;
}

/**
* Add to the order {@link #spec}.
*
* @param key
* @param direction
*/
final void add(String key, Direction direction) {
Preconditions.checkState(!built, "Cannot modify a built Order");
spec.put(key, direction.coefficient());
this.lastKey = key;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2013-2019 Cinchapi Inc.
*
* Licensed 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.
*/
package com.cinchapi.concourse.lang.sort;

/**
* The {@link OrderState} that expects the next token to be a sort order or a
* new key
* to sort by.
*/
public class OrderByState extends BuildableOrderState {

/**
* Construct a new instance.
*
* @param order
*/
OrderByState(Order order, String key, Direction direction) {
super(order);
order.add(key, direction);
}

/**
* Add the {@link Direction#ASCENDING} direction to the last key that
* was specified in {@link Order} that is building
*
* @return the builder
*/
public OrderDirectionState ascending() {
return new OrderDirectionState(order, order.lastKey,
Direction.ASCENDING);
}

/**
* Alias for {@link #descending()}.
*
* @return the builder
*/
public OrderDirectionState decreasing() {
return descending();
}

/**
* Add the {@link Direction#DESCENDING} direction to the last key that
* was specified in {@link Order} that is building
*
* @return the builder
*/
public OrderDirectionState descending() {
return new OrderDirectionState(order, order.lastKey,
Direction.DESCENDING);
}

/**
* Alias for {@link #ascending()}.
*
* @return the builder
*/
public OrderDirectionState increasing() {
return ascending();
}

/**
* Alias for {@link #descending()}.
*
* @return the builder
*/
public OrderDirectionState largestFirst() {
return descending();
}

/**
* Alias for {@link #ascending()}.
*
* @return the builder
*/
public OrderDirectionState largestLast() {
return ascending();
}

/**
* Alias for {@link #descending()}.
*
* @return the builder
*/
public OrderDirectionState reversed() {
return descending();
}

/**
* Alias for {@link #ascending()}.
*
* @return the builder
*/
public OrderDirectionState smallestFirst() {
return ascending();
}

/**
* Alias for {@link #descending()}.
*
* @return the builder
*/
public OrderDirectionState smallestLast() {
return descending();
}

/**
* Adds a new {@link SortOrder} to sort by to the {@link Order} that is
* building.
*
* @return the builder
*/
public OrderThenState then() {
return new OrderThenState(order);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2013-2019 Cinchapi Inc.
*
* Licensed 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.
*/
package com.cinchapi.concourse.lang.sort;

/**
* A {@link State} that represents a building {@link Order} that just had
* direction information specified for the most recently added key.
*
* @author Jeff Nelson
*/
public class OrderDirectionState extends BuildableOrderState {

/**
* Construct a new instance.
*
* @param order
*/
OrderDirectionState(Order order, String key, Direction direction) {
super(order);
order.add(key, direction);
}

/**
* Specify a transition to adding a new key to the order.
*
* @return the builder
*/
public OrderThenState then() {
return new OrderThenState(order);
}

}
Loading