/** * Copyright 2011 Google Inc. * * 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 org.waveprotocol.wave.migration.helpers; import org.waveprotocol.wave.client.common.util.WaveRefConstants; import org.waveprotocol.wave.model.document.operation.Nindo.NindoCursor; import org.waveprotocol.wave.model.document.operation.NindoCursorDecorator; import org.waveprotocol.wave.model.id.InvalidIdException; import org.waveprotocol.wave.model.id.WaveId; import org.waveprotocol.wave.model.waveref.InvalidWaveRefException; import org.waveprotocol.wave.model.waveref.WaveRef; import org.waveprotocol.wave.util.escapers.jvm.JavaWaverefEncoder; /** * Renames both "link/manual" and "link/wave" annotations to just "link". * * In cases where they would conflict, link/manual's value wins. Also, * link/wave's wave id is converted to a wave://waveref URI format. * * Also, replaces all instances of "waveid://" with simply "wave://", * and fixes waveids to be wave refs. This also applies to link/auto: * it is not renamed, but its values are still normalized. * * @author danilatos@google.com (Daniel Danilatos) */ public class FixLinkAnnotationsFilter extends NindoCursorDecorator { static final String OLD_MANUAL = "link/manual"; static final String OLD_WAVE = "link/wave"; static final String AUTO = "link/auto"; static final String NEW = "link"; static final String OLD_PREFIX = "waveid://"; private boolean manualOpen; private boolean waveOpen; private String currentManual; private String currentWave; public FixLinkAnnotationsFilter(NindoCursor target) { super(target); } @Override public void begin() { currentManual = null; currentWave = null; manualOpen = false; waveOpen = false; target.begin(); } @Override public void finish() { target.finish(); assert currentManual == null; assert currentWave == null; assert manualOpen == false; assert waveOpen == false; } @Override public void startAnnotation(String key, String value) { if (OLD_MANUAL.equals(key)) { manualOpen = true; currentManual = normalize(value); startLink(); } else if (OLD_WAVE.equals(key)) { try { currentWave = linkValueFromWaveValue(value); } catch (InvalidWaveRefException e) { // Discard invalid links. closeWave(); return; } waveOpen = true; if (!manualOpen) { startLink(); } } else if (AUTO.equals(key)) { super.startAnnotation(key, normalize(value)); } else { super.startAnnotation(key, value); } } @Override public void endAnnotation(String key) { if (OLD_MANUAL.equals(key)) { manualOpen = false; currentManual = null; if (waveOpen) { startLink(); } else { endLink(); } } else if (OLD_WAVE.equals(key)) { closeWave(); } else { super.endAnnotation(key); } } void closeWave() { if (waveOpen) { waveOpen = false; currentWave = null; if (!manualOpen) { endLink(); } } } void startLink() { assert manualOpen || waveOpen; super.startAnnotation(NEW, manualOpen ? currentManual : currentWave); } void endLink() { assert !manualOpen && !waveOpen && (currentManual == null) && (currentWave == null); super.endAnnotation(NEW); } public static String normalize(String oldHref) { if (oldHref.startsWith(OLD_PREFIX)) { try { return linkValueFromWaveValue(oldHref.substring(OLD_PREFIX.length())); } catch (InvalidWaveRefException e) { return null; } } else { return oldHref; } } public static String linkValueFromWaveValue(String rawString) throws InvalidWaveRefException { if (rawString == null) { return null; } WaveRef ref; try { ref = WaveRef.of(WaveId.checkedDeserialise(rawString)); } catch (InvalidIdException e) { // Let's try decoding it as a wave ref instead ref = JavaWaverefEncoder.decodeWaveRefFromPath(rawString); } return WaveRefConstants.WAVE_URI_PREFIX + JavaWaverefEncoder.encodeToUriPathSegment(ref); } }