Java tutorial
/* * Copyright 2012 Erlend Hamnaberg * * 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 net.hamnaberg.json; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import java.net.URI; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import net.hamnaberg.json.extension.Extended; import static java.util.Optional.of; import static java.util.Optional.ofNullable; public final class Collection extends Extended<Collection> implements Writable { Collection(ObjectNode value) { super(value); } @Override protected Collection copy(ObjectNode value) { return new Collection(value); } public static Collection create(URI href, List<Link> links, List<Item> items, List<Query> queries, Template template, Error error) { return create(ofNullable(href), links, items, queries, ofNullable(template), ofNullable(error)); } public static Collection create(Optional<URI> href, List<Link> links, List<Item> items, List<Query> queries, Optional<Template> template, Optional<Error> error) { ObjectNode obj = JsonNodeFactory.instance.objectNode(); obj.put("version", Version.ONE.getIdentifier()); href.ifPresent(value -> obj.put("href", value.toString())); if (!links.isEmpty()) { obj.set("links", links.stream().map(Extended::asJson).collect(JsonNodeFactory.instance::arrayNode, ArrayNode::add, ArrayNode::addAll)); } if (!items.isEmpty()) { obj.set("items", items.stream().map(Extended::asJson).collect(JsonNodeFactory.instance::arrayNode, ArrayNode::add, ArrayNode::addAll)); } if (!queries.isEmpty()) { obj.set("queries", queries.stream().map(Extended::asJson).collect(JsonNodeFactory.instance::arrayNode, ArrayNode::add, ArrayNode::addAll)); } template.ifPresent(value -> obj.set("template", value.asJson())); error.ifPresent(value -> obj.set("error", value.asJson())); Collection coll = new Collection(obj); coll.validate(); return coll; } public Version getVersion() { return Version.ONE; } public Optional<URI> getHref() { return delegate.has("href") ? of(URI.create(delegate.get("href").asText())) : Optional.<URI>empty(); } public List<Link> getLinks() { return delegate.has("links") ? Link.fromArray(delegate.get("links")) : Collections.<Link>emptyList(); } public List<Item> getItems() { return delegate.has("items") ? Item.fromArray(delegate.get("items")) : Collections.<Item>emptyList(); } public List<Query> getQueries() { return delegate.has("queries") ? Query.fromArray(delegate.get("queries")) : Collections.<Query>emptyList(); } public boolean hasTemplate() { return delegate.has("template"); } public Optional<Template> getTemplate() { return hasTemplate() ? of(new Template((ObjectNode) delegate.get("template"))) : Optional.<Template>empty(); } public boolean hasError() { return delegate.has("error"); } public Optional<Error> getError() { return hasError() ? of(new Error((ObjectNode) delegate.get("error"))) : Optional.<Error>empty(); } public Optional<Link> linkByName(final String name) { return findLink(link -> ofNullable(name).equals(link.getName())); } public Optional<Link> linkByRelAndName(final String rel, final String name) { return findLink(link -> rel.equals(link.getRel()) && ofNullable(name).equals(link.getName())); } public Optional<Link> linkByRel(final String rel) { return findLink(link -> rel.equals(link.getRel())); } public List<Link> linksByRel(final String rel) { return filterLinks(link -> rel.equals(link.getRel())); } public Optional<Query> queryByRel(final String rel) { return findQuery(query -> rel.equals(query.getRel())); } public Optional<Query> queryByName(final String name) { return findQuery(query -> ofNullable(name).equals(query.getName())); } public Optional<Query> queryByRelAndName(final String rel, final String name) { return findQuery(query -> rel.equals(query.getRel()) && ofNullable(name).equals(query.getName())); } public Optional<Link> findLink(Predicate<Link> predicate) { return getLinks().stream().filter(predicate).findFirst(); } public List<Link> filterLinks(Predicate<Link> predicate) { return getLinks().stream().filter(predicate).collect(Collectors.<Link>toList()); } public Optional<Item> findItem(Predicate<Item> predicate) { return getItems().stream().filter(predicate).findFirst(); } public List<Item> filterItems(Predicate<Item> predicate) { return getItems().stream().filter(predicate).collect(Collectors.<Item>toList()); } public List<Item> filterItemsByProfile(final URI profile) { return filterItems( item -> item.linkByRel("profile").map(link -> link.getHref().equals(profile)).orElse(true)); } public Optional<Item> getFirstItem() { return getItems().stream().findFirst(); } public Optional<Query> findQuery(Predicate<Query> predicate) { return getQueries().stream().filter(predicate).findFirst(); } public List<Query> filterQueries(Predicate<Query> predicate) { return getQueries().stream().filter(predicate).collect(Collectors.<Query>toList()); } public Builder toBuilder() { Builder builder = new Builder(getHref()); builder.addItems(getItems()); builder.addLinks(getLinks()); builder.addQueries(getQueries()); getTemplate().ifPresent(builder::withTemplate); getError().ifPresent(builder::withError); return builder; } public void writeTo(OutputStream stream) throws IOException { writeTo(new OutputStreamWriter(stream, Charset.forName("UTF-8"))); } public void writeTo(Writer writer) throws IOException { ObjectMapper mapper = new ObjectMapper(); ObjectNode obj = mapper.createObjectNode(); obj.set("collection", asJson()); mapper.writeValue(writer, obj); } @Override public String toString() { StringWriter writer = new StringWriter(); try { writeTo(writer); } catch (IOException ignore) { } return writer.toString(); } public void validate() { getLinks().stream().forEach(Link::validate); getItems().stream().forEach(Item::validate); getQueries().stream().forEach(Query::validate); getTemplate().ifPresent(Template::validate); getError().ifPresent(Error::validate); } public static Builder builder(URI href) { return new Builder(ofNullable(href)); } public static Builder builder() { return new Builder(); } public static class Builder { private Optional<URI> href; private final List<Item> itemBuilder = new ArrayList<Item>(); private final List<Link> linkBuilder = new ArrayList<Link>(); private final List<Query> queryBuilder = new ArrayList<Query>(); private Optional<Template> template = Optional.empty(); private Optional<Error> error = Optional.empty(); public Builder() { this(Optional.<URI>empty()); } public Builder(URI href) { this(ofNullable(href)); } public Builder(Optional<URI> href) { this.href = href; } public Builder withHref(URI href) { this.href = ofNullable(href); return this; } public Builder addItem(Item item) { itemBuilder.add(item); return this; } public Builder addItems(Iterable<Item> items) { addToList(items, itemBuilder); return this; } public Builder addQuery(Query query) { queryBuilder.add(query); return this; } public Builder addQueries(Iterable<Query> queries) { addToList(queries, queryBuilder); return this; } public Builder addLink(Link link) { linkBuilder.add(link); return this; } public Builder addLinks(Iterable<Link> links) { addToList(links, linkBuilder); return this; } public Builder withError(Error error) { this.error = ofNullable(error); return this; } public Builder withTemplate(Template template) { this.template = ofNullable(template); return this; } private <A> void addToList(Iterable<A> iterable, List<A> list) { StreamSupport.stream(iterable.spliterator(), false).forEach(list::add); } public Collection build() { return Collection.create(href, linkBuilder, itemBuilder, queryBuilder, template, error); } } }