/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.cxf.aegis.type.encoded; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import org.apache.cxf.aegis.Context; /** * MarshalRegistry maintains tracks which object instances have been marshaled * and which objects still need to be marshaled. * <p/> * Note: only the StructType register objects with this class. */ public class MarshalRegistry implements Iterable<Object> { /** * All objects instances with ids. It is CRITICAL that is be an IdentityHashMap to assure we don't * exclude instances that are equivilant but different instances. */ private final Map<Object, String> instances = new IdentityHashMap<Object, String>(); /** * The objects not yet marshaled. The is maintained as a map for debugging purposes. It is IMPORTANT * that this be a LinkedHashMap so we write the objects in the order they were discovered in the object * graphs (and writes them in numeric order). */ private final Map<String, Object> notMarshalled = new LinkedHashMap<String, Object>(); /** * The next id. */ private int nextId; /** * Get the MarshalRegistry stored in the context, and if necessary create a new one. * * @param context the unmarshal context * @return the SoapRefRegistry; never null */ public static MarshalRegistry get(Context context) { MarshalRegistry marshalRegistry = context.getProperty(MarshalRegistry.class); if (marshalRegistry == null) { marshalRegistry = new MarshalRegistry(); context.setProperty(marshalRegistry); } return marshalRegistry; } public String getInstanceId(Object instance) { String id = instances.get(instance); if (id == null) { id = "" + nextId++; instances.put(instance, id); notMarshalled.put(id, instance); } return id; } /** * Returns an iterator over the object instances that have not been marshalled yet. As each instance in * this iterator is written, it may contain references to additional objects that have not been written. * Those references objects will be added to the end of this iterator, so the "list" that is being * iterated over grows as the iteration preceeds. * <p/> * When an instance is returned from this iterator it is marked as marshalled. * * @return an iterator over the objects to be marshalled. */ public Iterator<Object> iterator() { return new Iterator<Object>() { public boolean hasNext() { return !notMarshalled.isEmpty(); } public Object next() { // remove the first entry in the notMarshalled map Iterator<Object> iterator = notMarshalled.values().iterator(); Object instance = iterator.next(); iterator.remove(); // return the instance return instance; } public void remove() { throw new UnsupportedOperationException(); } }; } }