146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmpackage com.xtremelabs.robolectric.tester.android.util; 2d8c89b8a0197b032b3f061c4738b349f29005272homeip.net!davidm 346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmimport android.util.AttributeSet; 4ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouximport android.view.View; 546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmimport com.xtremelabs.robolectric.res.AttrResourceLoader; 646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmimport com.xtremelabs.robolectric.res.ResourceExtractor; 746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmimport com.xtremelabs.robolectric.util.I18nException; 846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmimport java.util.*; 1046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 1146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidmpublic class TestAttributeSet implements AttributeSet { 1246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm Map<String, String> attributes = new HashMap<String, String>(); 1346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private ResourceExtractor resourceExtractor; 1446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private AttrResourceLoader attrResourceLoader; 1546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private Class<? extends View> viewClass; 1646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private boolean isSystem = false; 1746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 1846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm /** 1946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm * Names of attributes to be validated for i18n-safe values. 2046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm */ 2146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private static final String strictI18nAttrs[] = { 2246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm "android:text", 2346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm "android:title", 2446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm "android:titleCondensed", 2546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm "android:summary" 2646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm }; 2746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 2846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public TestAttributeSet() { 29d4a4ddd23d5a059c0b1a637fee5de78b6158eecdKonstantin Belousov this(new HashMap<String, String>()); 30d4a4ddd23d5a059c0b1a637fee5de78b6158eecdKonstantin Belousov } 3146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 3246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public TestAttributeSet(Map<String, String> attributes, ResourceExtractor resourceExtractor, 3346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm AttrResourceLoader attrResourceLoader, Class<? extends View> viewClass, boolean isSystem) { 3446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.attributes = attributes; 35a9b5b10f23fe0f55e39fece22d5d4bfdf7f3bdfeTommi Rantala this.resourceExtractor = resourceExtractor; 3646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.attrResourceLoader = attrResourceLoader; 3746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.viewClass = viewClass; 3846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.isSystem = isSystem; 3946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 4046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 4146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public TestAttributeSet(Map<String, String> attributes) { 4246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.attributes = attributes; 4346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.resourceExtractor = new ResourceExtractor(); 4446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.attrResourceLoader = new AttrResourceLoader(this.resourceExtractor); 4546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm this.viewClass = null; 4646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 4746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 4846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public TestAttributeSet put(String name, String value) { 4946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm attributes.put(name, value); 5046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return this; 5146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 5246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 5346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 5446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue) { 5546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = getAttributeValueInMap(namespace, attribute); 5646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return (value != null) ? Boolean.valueOf(value) : defaultValue; 5746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 5846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 5946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 6046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getAttributeValue(String namespace, String attribute) { 6146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return getAttributeValueInMap(namespace, attribute); 6246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 6346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 6446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 6546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeIntValue(String namespace, String attribute, int defaultValue) { 6646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = getAttributeValueInMap(namespace, attribute); 6746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 6846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (attrResourceLoader.hasAttributeFor(viewClass, "xxx", attribute)) { 6946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm value = attrResourceLoader.convertValueToEnum(viewClass, "xxx", attribute, value); 7046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 7146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 7246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return (value != null) ? Integer.valueOf(value) : defaultValue; 7346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 7446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 7546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 7646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeCount() { 7746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 7846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 7946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 8046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 8146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getAttributeName(int index) { 8246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 8346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 8446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 8546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 8646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getAttributeValue(int index) { 8746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 8846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 8946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 9046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 9146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getPositionDescription() { 9246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 9346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 9446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 9546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 9646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeNameResource(int index) { 9746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 9846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 9946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 10046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 10146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue) { 10246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 10346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 10446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 10546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 10646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) { 10746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 10846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 10946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 11046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 11146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) { 11246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = getAttributeValueInMap(namespace, attribute); 11346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 11446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (attrResourceLoader.hasAttributeFor(viewClass, "xxx", attribute)) { 11546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm value = attrResourceLoader.convertValueToEnum(viewClass, "xxx", attribute, value); 11646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 11746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 11846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return (value != null) ? Float.valueOf(value) : defaultValue; 11946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 12046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 12146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 12246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeListValue(int index, String[] options, int defaultValue) { 12346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 12446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 12546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 12646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 12746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public boolean getAttributeBooleanValue(int resourceId, boolean defaultValue) { 12846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 12946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 13046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 13146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 13246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { 13346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = getAttributeValueInMap(namespace, attribute); 13446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm Integer resourceId = defaultValue; 13546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (value != null) { 13646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm resourceId = resourceExtractor.getResourceId(value); 13746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 13846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return resourceId == null ? defaultValue : resourceId; 13946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 14046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 14146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 14246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeResourceValue(int resourceId, int defaultValue) { 14346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String attrName = resourceExtractor.getResourceName(resourceId); 14446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = getAttributeValueInMap(null, attrName); 14546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return (value == null) ? defaultValue : resourceExtractor.getResourceId(value); 14646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 14746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 14846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 14946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeIntValue(int index, int defaultValue) { 15046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 15146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 15246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 15346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 15446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getAttributeUnsignedIntValue(int index, int defaultValue) { 15546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 15646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 15746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 15846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 15946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public float getAttributeFloatValue(int index, float defaultValue) { 16046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 16146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 16246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 16346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 16446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getIdAttribute() { 16546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 16646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 16746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 16846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 16946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public String getClassAttribute() { 17046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 17146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 17246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 17346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 17446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getIdAttributeResourceValue(int defaultValue) { 17546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 17646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 17746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 17846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm @Override 17946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public int getStyleAttribute() { 18046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new UnsupportedOperationException(); 18146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 18246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 18346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm public void validateStrictI18n() { 18446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm for (int i = 0; i < strictI18nAttrs.length; i++) { 18546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String key = strictI18nAttrs[i]; 18646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (attributes.containsKey(key)) { 18746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = attributes.get(key); 18846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (!value.startsWith("@string/")) { 18946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm throw new I18nException("View class: " + (viewClass != null ? viewClass.getName() : "") + 19046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm " has attribute: " + key + " with hardcoded value: \"" + value + "\" and is not i18n-safe."); 19146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 19246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 19346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 19446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 19546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 19646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm private String getAttributeValueInMap(String namespace, String attribute) { 19746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String value = null; 19846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm for (String key : attributes.keySet()) { 19946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm String[] mappedKeys = {null, key}; 20046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (key.contains(":")) { 20146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm mappedKeys = key.split(":"); 20246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 20346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm 20446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (mappedKeys[1].equals(attribute) && ( 20546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm namespace == null || namespace != "android" || 20646c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm (namespace.equals("android") && namespace.equals(mappedKeys[0])))) { 20746c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm value = attributes.get(key); 20846c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm break; 20946c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 21046c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 21146c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm if (value != null && isSystem && value.startsWith("@+id")) { 21246c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm value = value.replace("@+id", "@+android:id"); 21346c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 21446c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm return value; 21546c0a3043e38a402c7d21bfad2ae08c6d889e194hp.com!davidm } 216828d48662d924988b9ac8554010cc72c53f9494bhp.com!davidm} 217828d48662d924988b9ac8554010cc72c53f9494bhp.com!davidm