/* Copyright (c) 2012-2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.api; import java.util.List; import java.util.Map; import org.geotools.filter.identity.FeatureIdVersionedImpl; import org.locationtech.geogig.api.plumbing.RevObjectParse; import org.opengis.feature.Feature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.FeatureType; import org.opengis.filter.identity.FeatureId; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; /** * Provides a method of building features from {@link RevFeature} objects that have the type * specified by the given {@link RevFeatureType}. * * @see RevFeatureType * @see RevFeature * @see Feature */ public class FeatureBuilder { private FeatureType featureType; private Map<String, Integer> attNameToRevTypeIndex; private RevFeatureType type; /** * Constructs a new {@code FeatureBuilder} with the given {@link RevFeatureType feature type}. * * @param type the feature type of the features that will be built */ public FeatureBuilder(RevFeatureType type) { this.type = type; this.featureType = type.type(); this.attNameToRevTypeIndex = GeogigSimpleFeature.buildAttNameToRevTypeIndex(type); } public RevFeatureType getType() { return type; } /** * Constructs a new {@code FeatureBuilder} with the given {@link SimpleFeatureType feature type} * . * * @param type the feature type of the features that will be built */ public FeatureBuilder(SimpleFeatureType type) { this(RevFeatureTypeImpl.build(type)); } /** * Builds a {@link Feature} from the provided {@link RevFeature}. * * @param id the id of the new feature * @param revFeature the {@code RevFeature} with the property values for the feature * @return the constructed {@code Feature} */ public Feature build(final String id, final RevFeature revFeature) { Preconditions.checkNotNull(id); Preconditions.checkNotNull(revFeature); final FeatureId fid = new LazyVersionedFeatureId(id, revFeature.getId()); ImmutableList<Optional<Object>> values = revFeature.getValues(); GeogigSimpleFeature feature = new GeogigSimpleFeature(values, (SimpleFeatureType) featureType, fid, attNameToRevTypeIndex); return feature; } public Feature buildLazy(final String id, final Node node, final RevObjectParse parser) { Supplier<? extends List<Optional<Object>>> valueSupplier = new LazyFeatureLoader( node.getObjectId(), parser); valueSupplier = Suppliers.memoize(valueSupplier); final FeatureId fid = new LazyVersionedFeatureId(id, node.getObjectId()); GeogigSimpleFeature feature = new GeogigSimpleFeature(valueSupplier, (SimpleFeatureType) featureType, fid, attNameToRevTypeIndex, node); return feature; } private static class LazyFeatureLoader implements Supplier<List<Optional<Object>>> { private ObjectId objectId; private RevObjectParse parser; public LazyFeatureLoader(ObjectId objectId, RevObjectParse parser) { this.objectId = objectId; this.parser = parser; } @Override public List<Optional<Object>> get() { Optional<RevFeature> revFeature = parser.setObjectId(objectId).call(RevFeature.class); return revFeature.get().getValues(); } } private static class LazyVersionedFeatureId extends FeatureIdVersionedImpl { private ObjectId version; public LazyVersionedFeatureId(String fid, ObjectId version) { super(fid, null); this.version = version; } @Override public String getFeatureVersion() { return version.toString(); } @Override public String getRid() { return new StringBuilder(getID()).append(VERSION_SEPARATOR).append(getFeatureVersion()) .toString(); } } }