# HG changeset patch # User Artem Tikhomirov # Date 1323177952 -3600 # Node ID 91d75e1bac9fce0afb4b51b8539c01042a676b4e # Parent f2c11fe7f3e9f3359b7a752094d787a86978dcee Consistent approach to deal with adaptable objects. Give adaptable precedence over instanceof to allow conditional response when classes do implement desired interface diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/core/HgCatCommand.java --- a/src/org/tmatesoft/hg/core/HgCatCommand.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/core/HgCatCommand.java Tue Dec 06 14:25:52 2011 +0100 @@ -205,13 +205,7 @@ if (CancelSupport.class == adapterClass) { return adapterClass.cast(cancelHelper); } - if (delegate instanceof Adaptable) { - return ((Adaptable) delegate).getAdapter(adapterClass); - } - if (adapterClass.isInstance(delegate)) { - return adapterClass.cast(delegate); - } - return null; + return Adaptable.Factory.getAdapter(delegate, adapterClass, null); } } } diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/internal/FilterByteChannel.java --- a/src/org/tmatesoft/hg/internal/FilterByteChannel.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/internal/FilterByteChannel.java Tue Dec 06 14:25:52 2011 +0100 @@ -59,9 +59,11 @@ public T getAdapter(Class adapterClass) { if (adapterClass == Preview.class) { ArrayList previewers = new ArrayList(filters.length); + Adaptable.Factory factory = new Adaptable.Factory(Preview.class); for (Filter f : filters) { - if (f instanceof Preview /*FIXME or getAdapter != null*/) { - previewers.add((Preview) f); + Preview p = factory.get(f); + if (p != null) { + previewers.add(p); } } if (!previewers.isEmpty()) { @@ -71,13 +73,7 @@ } // fall through to let delegate answer } - if (delegate instanceof Adaptable) { - return ((Adaptable) delegate).getAdapter(adapterClass); - } - if (adapterClass != null && adapterClass.isInstance(delegate)) { - return adapterClass.cast(delegate); - } - return null; + return Adaptable.Factory.getAdapter(delegate, adapterClass, null); } private static class PreviewSupport implements Preview { diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/internal/NewlineFilter.java --- a/src/org/tmatesoft/hg/internal/NewlineFilter.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/internal/NewlineFilter.java Tue Dec 06 14:25:52 2011 +0100 @@ -31,6 +31,7 @@ import org.tmatesoft.hg.core.HgBadStateException; import org.tmatesoft.hg.repo.HgInternals; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.Path; /** @@ -38,7 +39,7 @@ * @author Artem Tikhomirov * @author TMate Software Ltd. */ -public class NewlineFilter implements Filter, Preview { +public class NewlineFilter implements Filter, Preview, Adaptable { // if processInconsistent is false, filter simply pass incorrect newline characters (single \r or \r\n on *nix and single \n on Windows) as is, // i.e. doesn't try to convert them into appropriate newline characters. @@ -65,8 +66,8 @@ } public ByteBuffer filter(ByteBuffer src) { - if (!previewDone) { - throw new HgBadStateException("This filter requires preview operation prior to actual filtering"); + if (!processInconsistent && !previewDone) { + throw new HgBadStateException("This filter requires preview operation prior to actual filtering when eol.only-consistent is true"); } if (!processInconsistent && foundLoneLF && foundCRLF) { // do not process inconsistent newlines @@ -86,6 +87,18 @@ } } + public T getAdapter(Class adapterClass) { + // conditionally through getAdapter + if (Preview.class == adapterClass) { + // when processInconsistent is false, we need to preview data stream to ensure line terminators are consistent. + // otherwise, no need to look into the stream + if (!processInconsistent) { + return adapterClass.cast(this); + } + } + return null; + } + private boolean prevBufLastByteWasCR = false; private boolean previewDone = false; @@ -93,7 +106,6 @@ previewDone = true; // guard if (processInconsistent) { // gonna handle them anyway, no need to check. TODO Do not implement Preview directly, but rather - // conditionally through getAdapter when processInconsistent is false (sic!) return; } if (foundLoneLF && foundCRLF) { diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Tue Dec 06 14:25:52 2011 +0100 @@ -40,6 +40,7 @@ import org.tmatesoft.hg.internal.ManifestRevision; import org.tmatesoft.hg.internal.PathScope; import org.tmatesoft.hg.internal.Preview; +import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.ByteChannel; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.FileInfo; @@ -470,7 +471,7 @@ is = f.newInputChannel(); ByteBuffer fb = ByteBuffer.allocate(min(1 + data.length * 2 /*to fit couple of lines appended; never zero*/, 8192)); FilterByteChannel filters = new FilterByteChannel(check, repo.getFiltersFromWorkingDirToRepo(p)); - Preview preview = filters.getAdapter(Preview.class); + Preview preview = Adaptable.Factory.getAdapter(filters, Preview.class, null); if (preview != null) { while (is.read(fb) != -1) { fb.flip(); diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/repo/Revlog.java --- a/src/org/tmatesoft/hg/repo/Revlog.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/repo/Revlog.java Tue Dec 06 14:25:52 2011 +0100 @@ -253,8 +253,8 @@ if (end == TIP) { end = lastRev; } - final RevisionInspector revisionInsp = getAdapter(inspector, RevisionInspector.class); - final ParentInspector parentInsp = getAdapter(inspector, ParentInspector.class); + final RevisionInspector revisionInsp = Adaptable.Factory.getAdapter(inspector, RevisionInspector.class, null); + final ParentInspector parentInsp = Adaptable.Factory.getAdapter(inspector, ParentInspector.class, null); final Nodeid[] allRevisions = parentInsp == null ? null : new Nodeid[end - start + 1]; content.iterate(start, end, false, new RevlogStream.Inspector() { @@ -273,15 +273,6 @@ } }); } - private static T getAdapter(Object o, Class adapterClass) { - if (adapterClass.isInstance(o)) { - return adapterClass.cast(o); - } - if (o instanceof Adaptable) { - return ((Adaptable) o).getAdapter(adapterClass); - } - return null; - } /** * MARKER @@ -624,7 +615,7 @@ prepare(revisionNumber, da); // XXX perhaps, prepare shall return DA (sliced, if needed) final ProgressSupport progressSupport = ProgressSupport.Factory.get(sink); ByteBuffer buf = ByteBuffer.allocate(actualLen > 8192 ? 8192 : actualLen); - Preview p = getAdapter(sink, Preview.class); + Preview p = Adaptable.Factory.getAdapter(sink, Preview.class, null); if (p != null) { progressSupport.start(2 * da.length()); while (!da.isEmpty()) { diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/util/Adaptable.java --- a/src/org/tmatesoft/hg/util/Adaptable.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/util/Adaptable.java Tue Dec 06 14:25:52 2011 +0100 @@ -25,4 +25,44 @@ public interface Adaptable { T getAdapter(Class adapterClass); + + class Factory { + + private final Class adapterClass; + + public Factory(Class adapterClass) { + assert adapterClass != null; + this.adapterClass = adapterClass; + } + + public T get(Object target) { + return getAdapter(target, adapterClass, null); + } + + public T get(Object target, T defaultValue) { + return getAdapter(target, adapterClass, defaultValue); + } + + /** + * Try to adapt target to specified class, resort to defaultValue when not possible. + * Instance lookup order is as follows: first, target is checked for being {@link Adaptable} and, if yes, + * consulted for adapter. Then, plain {@link Class#isInstance(Object) instanceof} checks if target itself is + * of desired type. {@link Adaptable} check comes first to allow classed that are in fact instanceof + * desired type to respond to the demand conditionally + * + * @param target object to adapt, null value, although meaningless, is tolerable. + * @param adapterClass desired target class + * @param defaultValue value to use if target cannot be adapted to desired class, may be null + * @return instance of the desired class + */ + public static C getAdapter(Object target, Class adapterClass, C defaultValue) { + if (target instanceof Adaptable) { + return ((Adaptable) target).getAdapter(adapterClass); + } + if (adapterClass.isInstance(target)) { + return adapterClass.cast(target); + } + return defaultValue; + } + } } diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/util/CancelSupport.java --- a/src/org/tmatesoft/hg/util/CancelSupport.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/util/CancelSupport.java Tue Dec 06 14:25:52 2011 +0100 @@ -54,16 +54,7 @@ } public static CancelSupport get(Object target, CancelSupport defaultValue) { - if (target instanceof CancelSupport) { - return (CancelSupport) target; - } - if (target instanceof Adaptable) { - CancelSupport cs = ((Adaptable) target).getAdapter(CancelSupport.class); - if (cs != null) { - return cs; - } - } - return defaultValue; + return Adaptable.Factory.getAdapter(target, CancelSupport.class, defaultValue); } } diff -r f2c11fe7f3e9 -r 91d75e1bac9f src/org/tmatesoft/hg/util/ProgressSupport.java --- a/src/org/tmatesoft/hg/util/ProgressSupport.java Tue Dec 06 12:57:21 2011 +0100 +++ b/src/org/tmatesoft/hg/util/ProgressSupport.java Tue Dec 06 14:25:52 2011 +0100 @@ -37,14 +37,9 @@ * @return support object extracted from target or an empty, no-op implementation */ public static ProgressSupport get(Object target) { - if (target instanceof ProgressSupport) { - return (ProgressSupport) target; - } - if (target instanceof Adaptable) { - ProgressSupport ps = ((Adaptable) target).getAdapter(ProgressSupport.class); - if (ps != null) { - return ps; - } + ProgressSupport ps = Adaptable.Factory.getAdapter(target, ProgressSupport.class, null); + if (ps != null) { + return ps; } return new ProgressSupport() { public void start(int totalUnits) {