Java tutorial
/** * Copyright 2010 CosmoCode GmbH * * 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 de.cosmocode.palava.model.geoplanet; import java.util.Collections; import java.util.Locale; import java.util.NoSuchElementException; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; import javax.persistence.Table; import org.apache.commons.lang.StringUtils; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import de.cosmocode.palava.model.base.ReadOnly; import de.cosmocode.palava.model.geo.AbstractToponym; import de.cosmocode.palava.model.geo.ToponymBase; import de.cosmocode.rendering.Renderer; import de.cosmocode.rendering.RenderingException; import de.cosmocode.rendering.RenderingLevel; /** * Concrete entity implementation of the {@link ToponymBase} interface. * * <p> * This class is part of the Palava Geoplanet package. * </p> * * @author Willi Schoenborn */ @Entity @Table(name = "geoplanet_places") @ReadOnly public final class Place extends AbstractToponym { @Column(name = "language_code") private String languageCode; @Column(name = "place_type") @Enumerated(EnumType.STRING) private PlaceType placeType; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn private Place parent; @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent") private Set<Place> children = Sets.newHashSet(); @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "geoplanet_neighbors", joinColumns = @JoinColumn(name = "place_id"), inverseJoinColumns = @JoinColumn(name = "neighbour_id")) private Set<Place> neighbors = Sets.newHashSet(); @OneToMany(fetch = FetchType.LAZY, mappedBy = "place") private Set<Alias> aliases = Sets.newHashSet(); /** * Pre-persist callback which prevents inserts. */ @PrePersist protected void prePersist() { throw new UnsupportedOperationException("Place is read-only"); } /** * Pre-update callback which prevents updates. */ @PreUpdate protected void preUpdate() { throw new UnsupportedOperationException("Place is read-only"); } /** * Pre-delete callback which prevents deletes. */ @PreRemove protected void preRemove() { throw new UnsupportedOperationException("Place is read-only"); } public String getLanguageCode() { return languageCode; } public PlaceType getPlaceType() { return placeType; } /** * Provide the parent of this place. * * @return the parent of this place or null if this place has no parent */ public Place getParent() { return parent; } public ImmutableSet<Place> getChildren() { return ImmutableSet.copyOf(children); } /** * Provide all siblings of this place. Siblings * share the same parent and have the same {@linkplain PlaceType place type}. * * <p> * This place is not considered a siblings of his own and therefore * not included in the returned set. * </p> * * @return an immutable set of all siblings */ public ImmutableSet<Place> getSiblings() { if (getParent() == null) return ImmutableSet.of(); return ImmutableSet.copyOf(Iterables.filter(getParent().getChildren(), new Predicate<Place>() { @Override public boolean apply(Place input) { if (input.getPlaceType() == Place.this.getPlaceType()) { return Place.this.equals(input); } else { return false; } } })); } /** * Provide all ancestors of this place. * * <p> * This place is not considered an ancestor of his own and therefore * not included in the returned set. * </p> * * @return an immutable set of all ancestors */ public ImmutableSet<Place> getAncestors() { return climbFamilyTree(ImmutableSet.<Place>builder()).build(); } private ImmutableSet.Builder<Place> climbFamilyTree(ImmutableSet.Builder<Place> builder) { if (getParent() == null) { return builder; } else { builder.add(getParent()); return getParent().climbFamilyTree(builder); } } public ImmutableSet<Place> getNeighbors() { return ImmutableSet.copyOf(neighbors); } @Override public Set<Alias> getAliases() { return Collections.unmodifiableSet(aliases); } /** * Retrieve the preferredAlias for a specified locale. * * @param locale the target locale * @return a preferred alias of this place for the given locale * @throws NoSuchElementException if there is no preferred alias for * the given locale */ public Alias getPreferredAlias(final Locale locale) { final String language = locale.getLanguage(); return Iterables.find(getAliases(), new Predicate<Alias>() { @Override public boolean apply(Alias input) { if (input.getNameType() == NameType.Q) { return StringUtils.equals(input.getLanguageCode(), language); } else { return false; } } }); } @Override public void render(Renderer renderer, RenderingLevel level) throws RenderingException { super.render(renderer, level); renderer.key("languageCode").value(getLanguageCode()).key("placeType").value(getPlaceType()); } }