litesoft
@ 939
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
// This Source Code is in the Public Domain per: http://litesoft.org/License.txt package org.litesoft.core.hierarchicaldata; import java.io.*; import org.litesoft.commonfoundation.typeutils.*; import java.util.*; import org.litesoft.commonfoundation.typeutils.Objects; /** * A List 'like' class that is type safe for <String>, <HDSList>, & <HDSMap>. * <p/> * It does NOT quite really implement the List interface because proper Concurrent Modification is not recognized. * For this reason, it is NOT coded to be Thread Safe! * <p/> * Note: AFAIK, Generics do not support multiple different types. */ public class HDSList extends AbstractList<Object> implements Serializable { private static final long serialVersionUID = 1L; public static final String TYPE = "HDSList"; private ArrayList<Entry> mEntries = new ArrayList<Entry>(); public HDSList() { } public int size() { return mEntries.size(); } public Object get( int index ) { return unwrapType( mEntries.get( index ) ); } @Override public Object set( int index, Object element ) { return unParent( unwrapType( mEntries.set( index, new Entry( this, element ) ) ) ); } @Override public void add( int index, Object element ) { mEntries.add( index, new Entry( this, element ) ); } @Override public Object remove( int index ) { return unParent( unwrapType( mEntries.remove( index ) ) ); } @Override public void clear() { if ( !mEntries.isEmpty() ) { super.clear(); } } private Object unParent( Object pObject ) { if ( pObject != null ) { if ( pObject instanceof HDSMap ) { ((HDSMap) pObject).setHDSParent( null ); } else if ( pObject instanceof HDSList ) { ((HDSList) pObject).setHDSParent( null ); } } return pObject; } private Object unwrapType( Entry pElement ) { return (pElement != null) ? pElement.getValue() : null; } public void desiccate( HierarchicalDataSink pSink ) { populate( pSink.createRootNode( TYPE ) ); } public void desiccate( HierarchicalDataSink.Node pParentNode ) { populate( pParentNode.createChildNode( TYPE ) ); } private void populate( HierarchicalDataSink.Node pNode ) { pNode.setAttribute( "size", "" + mEntries.size() ); for ( Entry zEntry : mEntries ) { zEntry.desiccate( pNode ); } pNode.done(); } public HDSList( HierarchicalDataSource.Node pNode ) { String zStrSize = Strings.assertNotNullNotEmpty( TYPE + " 'size' attribute", pNode.getAttributeValue( "size" ) ); int zExpectedSize; try { zExpectedSize = Integer.parseInt( zStrSize ); } catch ( NumberFormatException e ) { throw new IllegalArgumentException( TYPE + " 'size' attribute Not Numeric", e ); } int zActualSize = 0; for ( HierarchicalDataSource.Node zNode; null != (zNode = pNode.getNextChild()); ) { zActualSize++; mEntries.add( new Entry( zNode ) ); } if ( zActualSize != zExpectedSize ) { throw new IllegalArgumentException( TYPE + " rehydrate, expected '" + zExpectedSize + "' members, but got: " + zActualSize ); } } static class Entry implements Serializable { // Use multiple variables as there is no "reasonable" (for Serializing) common parent protected String mValueAsLocalString; protected HDSMap mValueAsChildMap; protected HDSList mValueAsChildList; Entry() { } Entry( Object pOwner, Object pValue ) { if ( pValue instanceof String ) { mValueAsLocalString = pValue.toString(); } else if ( pValue instanceof HDSMap ) { (mValueAsChildMap = (HDSMap) pValue).setHDSParent( pOwner ); } else if ( pValue instanceof HDSList ) { (mValueAsChildList = (HDSList) pValue).setHDSParent( pOwner ); } else if ( pValue == null ) { throw new NullPointerException( "Value" ); } else { throw new IllegalArgumentException( "Unsupported Type: " + pValue ); } } public Object getValue() { return (mValueAsLocalString != null) ? mValueAsLocalString : (mValueAsChildMap != null) ? mValueAsChildMap : mValueAsChildList; } public String getValueAsLocalString() { return mValueAsLocalString; } public HDSMap getValueAsChildMap() { return mValueAsChildMap; } public HDSList getValueAsChildList() { return mValueAsChildList; } public void desiccate( HierarchicalDataSink.Node pParentNode ) { if ( getValueAsLocalString() != null ) { HierarchicalDataSink.Node zNode = pParentNode.createChildNode( "String" ); zNode.setAttribute( "of", getValueAsLocalString() ); zNode.done(); } else if ( getValueAsChildMap() != null ) { getValueAsChildMap().desiccate( pParentNode ); } else { getValueAsChildList().desiccate( pParentNode ); } } Entry( HierarchicalDataSource.Node pNode ) { String zName = pNode.getName(); if ( "String".equals( zName ) ) { Objects.assertNotNull( "String Value", mValueAsLocalString = pNode.getAttributeValue( "of" ) ); } else if ( HDSMap.TYPE.equals( zName ) ) { mValueAsChildMap = new HDSMap( pNode ); } else if ( HDSList.TYPE.equals( zName ) ) { mValueAsChildList = new HDSList( pNode ); } else { throw new IllegalArgumentException( "Unrecognized " + TYPE + " Member Node of: " + zName ); } pNode.assertNoMoreChildren(); } } private transient Object mHDSParent = null; void setHDSParent( Object pHDSParent ) { if ( (pHDSParent != null) && (mHDSParent != null) ) { throw new IllegalStateException( "An " + TYPE + " may only be 'held' by ONE other HDS 'type' (" + HDSMap.TYPE + " or " + TYPE + ")" ); } mHDSParent = pHDSParent; } } |
Commits for litesoft/trunk/Java/core/Anywhere/src/org/litesoft/core/hierarchicaldata/HDSList.java
Revision | Author | Commited | Message |
---|---|---|---|
939 Diff | GeorgeS | Mon 02 Jun, 2014 21:30:31 +0000 | Extracting commonfoundation |
917 Diff | GeorgeS | Sun 08 Dec, 2013 20:49:56 +0000 | 1.7 prep & VersionedStaticContentFilter upgrade to new “/ver” model! |
849 Diff | GeorgeS | Tue 11 Sep, 2012 17:11:59 +0000 | Clean up serialization |
821 Diff | GeorgeS | Sun 19 Aug, 2012 00:08:41 +0000 | |
804 Diff | GeorgeS | Wed 15 Aug, 2012 12:48:51 +0000 | |
151 Diff | GeorgeS | Thu 17 Mar, 2011 04:16:22 +0000 | |
49 Diff | GeorgeS | Mon 12 Apr, 2010 02:59:10 +0000 | License Text |
2 | GeorgeS | Sun 07 Feb, 2010 12:50:58 +0000 |