com.github.thinkerou.demo.helloworld.HelloWorldServerImpl Maven / Gradle / Ivy
package com.github.thinkerou.demo.helloworld;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import static java.lang.Math.toRadians;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
/**
* HelloWorldServerImpl
*
* Source from: https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples
*
* @author thinkerou
*/
public class HelloWorldServerImpl extends GreeterGrpc.GreeterImplBase {
private static final Logger logger = Logger.getLogger(HelloWorldServerImpl.class.getName());
private static final int STREAM_MESSAGE_NUMBER = 3;
private static final long STREAM_SLEEP_MILLIS = 10;
private static final double COORD_FACTOR = 1e7;
private final Collection features;
private final ConcurrentMap> routeNotes = new ConcurrentHashMap>();
HelloWorldServerImpl(Collection features) {
this.features = features;
}
@Override
public void sayHello(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void againSayHello(AgainHelloRequest req, StreamObserver responseObserver) {
AgainHelloReply reply = AgainHelloReply.newBuilder()
.setDetails("Details " + req.getMessage() + " in " + req.getAddress())
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void sayHelloServerStreaming(HelloRequest request, StreamObserver replyStreamObserver) {
for (int i = 0; i < STREAM_MESSAGE_NUMBER; i++) {
HelloReply helloReply = HelloReply.newBuilder()
.setMessage("Hello " + request.getName() + " part " + i)
.build();
replyStreamObserver.onNext(helloReply);
try {
Thread.sleep(STREAM_SLEEP_MILLIS);
} catch (InterruptedException e) {
replyStreamObserver.onError(Status.ABORTED.asException());
}
}
replyStreamObserver.onCompleted();
}
@Override
public StreamObserver sayHelloClientStreaming(final StreamObserver replyStreamObserver) {
return new StreamObserver() {
String out = "";
@Override
public void onNext(HelloRequest helloRequest) {
if (out == "") {
out = helloRequest.getName();
} else {
out += " and " + helloRequest.getName();
}
}
@Override
public void onError(Throwable throwable) {
logger.warning(throwable.getMessage());
}
@Override
public void onCompleted() {
HelloReply helloReply = HelloReply.newBuilder()
.setMessage("Hello " + out)
.build();
replyStreamObserver.onNext(helloReply);
replyStreamObserver.onCompleted();
}
};
}
@Override
public StreamObserver sayHelloBiStreaming(final StreamObserver responseObserver) {
// Give gRPC a StreamObserver that can observe and process incoming requests.
return new StreamObserver() {
@Override
public void onNext(HelloRequest request) {
// Process the request and send a response or an error.
try {
// Accept and enqueue the request.
String name = request.getName();
// Simulate server "work"
Thread.sleep(STREAM_SLEEP_MILLIS);
// Send a response.
String message = "Hello " + name;
HelloReply reply = HelloReply.newBuilder().setMessage(message).build();
responseObserver.onNext(reply);
} catch (Throwable throwable) {
throwable.printStackTrace();
responseObserver.onError(
Status.UNKNOWN.withDescription("Error handling request").withCause(throwable).asException());
}
}
@Override
public void onError(Throwable t) {
// End the response stream if the client presents an error.
t.printStackTrace();
responseObserver.onCompleted();
}
@Override
public void onCompleted() {
// Signal the end of work when the client ends the request stream.
responseObserver.onCompleted();
}
};
}
// The following part comes from:
// https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/routeguide
/**
* getFeature: single grpc
*
* Gets the Feature at the requested Point.
* If no feature at that location exists, an unnamed feature is returned at the provided location.
*/
@Override
public void getFeature(Point request, StreamObserver responseObserver) {
responseObserver.onNext(checkFeature(request));
responseObserver.onCompleted();
}
/**
* listFeaturs: server stream grpc
*
* Gets all features contained within the given bounding Rectangle.
*/
@Override
public void listFeatures(Rectangle request, StreamObserver responseObserver) {
int left = min(request.getLo().getLongitude(), request.getHi().getLongitude());
int right = max(request.getLo().getLongitude(), request.getHi().getLongitude());
int top = max(request.getLo().getLatitude(), request.getHi().getLatitude());
int bottom = min(request.getLo().getLatitude(), request.getHi().getLatitude());
for (Feature feature : features) {
if (!exists(feature)) {
continue;
}
int lat = feature.getLocation().getLatitude();
int lon = feature.getLocation().getLongitude();
if (lon >= left && lon <= right && lat >= bottom && lat <= top) {
responseObserver.onNext(feature);
}
}
responseObserver.onCompleted();
}
/**
* recordRoute: client stream grpc
*
* Gets a stream of points, and responds with statistics about the "trip": number of points,
* number of known features visited, total distance traveled, and total time spent.
*/
@Override
public StreamObserver recordRoute(final StreamObserver responseObserver) {
return new StreamObserver() {
int pointCount;
int featureCount;
int distance;
Point previous;
final long startTime = System.nanoTime();
@Override
public void onNext(Point point) {
pointCount++;
if (exists(checkFeature(point))) {
featureCount++;
}
if (previous != null) {
distance += calcDistance(previous, point);
}
previous = point;
}
@Override
public void onError(Throwable throwable) {
logger.warning("RecordRoute cancelled");
}
@Override
public void onCompleted() {
long seconds = NANOSECONDS.toSeconds(System.nanoTime() - startTime);
responseObserver.onNext(RouteSummary.newBuilder().
setPointCount(pointCount)
.setFeatureCount(featureCount)
.setDistance(distance)
.setElapsedTime((int) seconds)
.build()
);
responseObserver.onCompleted();
}
};
}
/**
* routeChat: bidi stream grpc
*
* Receives a stream of message/location pairs, and responds with a stream of all previous
* messages at each of those locations.
*/
@Override
public StreamObserver routeChat(final StreamObserver responseObserver) {
return new StreamObserver() {
@Override
public void onNext(RouteNote routeNote) {
List notes = getOrCreateNotes(routeNote);
for (RouteNote preNote : notes.toArray(new RouteNote[0])) {
responseObserver.onNext(preNote);
}
notes.add(routeNote);
}
@Override
public void onError(Throwable throwable) {
logger.warning("RouteChat cancelled");
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
/**
* Gets the notes list for the given location. If missing, create it.
*/
private List getOrCreateNotes(RouteNote routeNote) {
List notes = Collections.synchronizedList(new ArrayList<>());
notes.add(routeNote);
List preNotes = routeNotes.putIfAbsent(routeNote.getLocation(), notes);
return preNotes != null ? preNotes : notes;
}
/**
* Gets the feature at the given point.
*/
private Feature checkFeature(Point location) {
for (Feature feature : features) {
if (feature.getLocation().getLongitude() == location.getLongitude() &&
feature.getLocation().getLatitude() == location.getLatitude()) {
return feature;
}
}
return Feature.newBuilder().setName("").setLocation(location).build();
}
/**
* Calculates the distance between two points using the "haversine" formula.
*/
private static int calcDistance(Point start, Point end) {
int r = 6371000; // earch radius in meters
double lat1 = toRadians(start.getLatitude() / COORD_FACTOR);
double lat2 = toRadians(end.getLatitude() / COORD_FACTOR);
double lon1 = toRadians(start.getLongitude() / COORD_FACTOR);
double lon2 = toRadians(end.getLongitude() / COORD_FACTOR);
double deltaLat = lat2 - lat1;
double deltaLon = lon2 - lon1;
double a = sin(deltaLat / 2) * sin(deltaLat / 2) + cos(lat1) * cos(lat2) * sin(deltaLon / 2) * sin(deltaLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return (int) (r * c);
}
/**
* Indicates whether the given feature exists.
*/
public static boolean exists(Feature feature) {
return feature != null && !feature.getName().isEmpty();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy