Package org.locationtech.geogig.api.plumbing.diff

Source Code of org.locationtech.geogig.api.plumbing.diff.PatchSerializer

/* Copyright (c) 2013-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:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.api.plumbing.diff;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.locationtech.geogig.api.FeatureBuilder;
import org.locationtech.geogig.api.FeatureInfo;
import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.RevFeature;
import org.locationtech.geogig.api.RevFeatureBuilder;
import org.locationtech.geogig.api.RevFeatureType;
import org.locationtech.geogig.api.RevObject;
import org.locationtech.geogig.api.RevObject.TYPE;
import org.locationtech.geogig.storage.ObjectReader;
import org.locationtech.geogig.storage.ObjectWriter;
import org.locationtech.geogig.storage.text.TextSerializationFactory;
import org.opengis.feature.Feature;
import org.opengis.feature.type.PropertyDescriptor;

import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
* Serializes the differences between two versions of the repository, in plain text format
*
* This is a very basic first version used to test patches created using a plain text format similar
* to the format output by the diff command. This should be extended to support other formats.
*
*/
public class PatchSerializer {

    private static TextSerializationFactory factory = new TextSerializationFactory();

    /**
     * Creates a patch object to apply on a GeoGig working tree
     *
     * @param reader the read from where to read the patch description
     * @return a Patch
     */
    public static Patch read(BufferedReader reader) {
        Preconditions.checkNotNull(reader);

        Patch patch = new Patch();
        List<String> subset = Lists.newArrayList();
        Map<String, RevFeatureType> featureTypes = Maps.newHashMap();
        try {
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.isEmpty() && !subset.isEmpty()) {
                    addElement(subset, patch, featureTypes);
                    subset.clear();
                } else if (!line.isEmpty()) {
                    subset.add(line);
                }
            }
            if (!subset.isEmpty()) {
                addElement(subset, patch, featureTypes);
            }
            Set<Entry<String, RevFeatureType>> entries = featureTypes.entrySet();
            for (Iterator<Entry<String, RevFeatureType>> iterator = entries.iterator(); iterator
                    .hasNext();) {
                Entry<String, RevFeatureType> entry = iterator.next();
                patch.addFeatureType(entry.getValue());
            }
            return patch;
        } catch (IOException e) {
            throw new IllegalArgumentException("Can't read patch: " + e.getMessage());
        }
    }

    private static void addElement(List<String> lines, Patch patch,
            Map<String, RevFeatureType> featureTypes) {
        String[] headerTokens = lines.get(0).split("\t");
        if (headerTokens.length == 4 || headerTokens.length == 3) {// feature or feature type
                                                                   // modified // modification
            if (lines.size() == 1) { // feature type
                FeatureTypeDiff diff = new FeatureTypeDiff(headerTokens[0],
                        ObjectId.valueOf(headerTokens[1]), ObjectId.valueOf(headerTokens[2]));
                patch.addAlteredTree(diff);
            } else {// feature
                String element = Joiner.on("\n").join(lines.subList(1, lines.size()));
                ByteArrayInputStream stream;
                stream = new ByteArrayInputStream(element.getBytes(Charsets.UTF_8));
                String operation = headerTokens[0].trim();
                if (operation.equals("M")) {
                    String fullPath = headerTokens[1].trim();
                    String oldMetadataId = headerTokens[2].trim();
                    String newMetadataId = headerTokens[3].trim();
                    RevFeatureType newRevFeatureType = featureTypes.get(newMetadataId);
                    RevFeatureType oldRevFeatureType = featureTypes.get(oldMetadataId);

                    Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap();
                    for (int i = 1; i < lines.size(); i++) {
                        addDifference(lines.get(i), map, oldRevFeatureType, newRevFeatureType);
                    }
                    FeatureDiff featureDiff = new FeatureDiff(fullPath, map, oldRevFeatureType,
                            newRevFeatureType);
                    patch.addModifiedFeature(featureDiff);
                } else if (operation.equals("A") || operation.equals("R")) {
                    String fullPath = headerTokens[1].trim();
                    String featureTypeId = headerTokens[2].trim();
                    RevFeatureType revFeatureType;
                    revFeatureType = featureTypes.get(featureTypeId);
                    FeatureBuilder featureBuilder = new FeatureBuilder(revFeatureType);
                    ObjectReader<RevFeature> reader = factory.createFeatureReader();
                    RevFeature revFeature = reader.read(null, stream);
                    Feature feature = featureBuilder.build(NodeRef.nodeFromPath(fullPath),
                            revFeature);
                    if (operation.equals("R")) {
                        patch.addRemovedFeature(fullPath, feature, revFeatureType);
                    } else {
                        patch.addAddedFeature(fullPath, feature, revFeatureType);
                    }
                } else {
                    throw new IllegalArgumentException("Wrong patch content: " + lines.get(0));
                }
            }

        } else if (headerTokens.length == 1) {// feature type definition
            String element = Joiner.on("\n").join(lines);
            ByteArrayInputStream stream = new ByteArrayInputStream(element.getBytes(Charsets.UTF_8));
            String[] tokens = lines.get(1).split("\t");
            ObjectReader<RevFeatureType> reader = factory.createFeatureTypeReader();
            RevFeatureType featureType = reader.read(null, stream);
            featureTypes.put(featureType.getId().toString(), featureType);
        } else {
            throw new IllegalArgumentException("Wrong patch content: " + lines.get(0));
        }

    }

    private static void addDifference(String s, Map<PropertyDescriptor, AttributeDiff> map,
            RevFeatureType oldRevFeatureType, RevFeatureType newRevFeatureType) {
        String[] tokens = s.split("\t");
        PropertyDescriptor descriptor = oldRevFeatureType.type().getDescriptor(tokens[0]);
        if (descriptor == null) {
            descriptor = newRevFeatureType.type().getDescriptor(tokens[0]);
        }
        AttributeDiff ad = AttributeDiffFactory.attributeDiffFromText(descriptor.getType()
                .getBinding(), s.substring(s.indexOf("\t") + 1));
        map.put(descriptor, ad);
    }

    public static void write(Writer w, Patch patch) throws IOException {
        StringBuilder sb = new StringBuilder();
        List<RevFeatureType> featureTypes = patch.getFeatureTypes();
        for (RevFeatureType featureType : featureTypes) {
            ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURETYPE);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            writer.write(featureType, output);
            sb.append(output.toString());
            sb.append('\n');
        }

        TextSerializationFactory factory = new TextSerializationFactory();
        for (FeatureInfo feature : patch.getAddedFeatures()) {
            String path = feature.getPath();
            sb.append("A\t" + path + "\t" + feature.getFeatureType().getId() + "\n");
            ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURE);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            RevFeature revFeature = RevFeatureBuilder.build(feature.getFeature());
            try {
                writer.write(revFeature, output);
            } catch (IOException e) {
            }
            sb.append(output.toString());
            sb.append('\n');
        }
        for (FeatureInfo feature : patch.getRemovedFeatures()) {
            String path = feature.getPath();
            sb.append("R\t" + path + "\t" + feature.getFeatureType().getId() + "\n");
            ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURE);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            RevFeature revFeature = RevFeatureBuilder.build(feature.getFeature());
            try {
                writer.write(revFeature, output);
            } catch (IOException e) {
            }
            sb.append(output.toString());
            sb.append('\n');
        }
        for (FeatureDiff diff : patch.getModifiedFeatures()) {
            sb.append("M\t" + diff.getPath() + "\t" + diff.getOldFeatureType().getId().toString()
                    + "\t" + diff.getNewFeatureType().getId().toString() + "\n");
            sb.append(diff.asText() + "\n");
        }
        for (FeatureTypeDiff diff : patch.getAlteredTrees()) {
            sb.append(diff.toString() + "\n");
        }

        w.write(sb.toString());
        w.flush();
    }

}
TOP

Related Classes of org.locationtech.geogig.api.plumbing.diff.PatchSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.