package com.framsticks.dumping; import static com.framsticks.core.InstanceUtils.*; import com.framsticks.core.Node; import com.framsticks.core.Path; import com.framsticks.params.AccessInterface; import com.framsticks.params.CompositeParam; import com.framsticks.params.FramsClass; import com.framsticks.params.ListAccess; import com.framsticks.params.SinkInterface; import com.framsticks.parsers.Savers; import com.framsticks.core.Instance; import com.framsticks.util.*; import com.framsticks.util.dispatching.Dispatching; import org.apache.log4j.Logger; import com.framsticks.util.dispatching.RunAt; import java.util.HashSet; import java.util.Set; import static com.framsticks.util.lang.Containers.filterInstanceof; /** * @author Piotr Sniegowski */ public class SaveStream extends Stream { private final static Logger log = Logger.getLogger(SaveStream.class.getName()); protected final SinkInterface sink; protected final Instance instance; protected final StateFunctor stateFunctor; protected final Stopwatch stopwatch = new Stopwatch(); protected final Set storedInfo = new HashSet(); private int dispatched = 0; public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) { assert Dispatching.isThreadSafe(); this.sink = sink; this.instance = instance; this.stateFunctor = stateFunctor; dispatchWrite(root); } protected void dispatchWrite(final Path path) { ++dispatched; instance.dispatch(new RunAt() { @Override public void run() { write(path); } }); } protected void finished() { assert instance.isActive(); log.info("stored in " + stopwatch); stateFunctor.call(); } public void write(final Path path) { assert instance.isActive(); if (!path.isResolved()) { log.debug("path " + path + " is not resolved - skipping"); } else { AccessInterface access = bindAccess(path); assert access != null; FramsClass framsClass = access.getFramsClass(); assert framsClass != null; if (!storedInfo.contains(framsClass)) { storedInfo.add(framsClass); sink.print("info ").print(path.getTextual()).breakLine(); sink.print("file").breakLine(); Savers.saveFramsClass(sink, framsClass); sink.print("eof").breakLine(); sink.print("ok").breakLine(); } if (!(access instanceof ListAccess)) { sink.print("get ").print(path.getTextual()).breakLine(); sink.print("file").breakLine(); //stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n"); access.save(sink); sink.print("eof").breakLine(); sink.print("ok").breakLine(); } for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) { final Path childPath = path.appendNode(new Node(p, access.get(p, Object.class))); if (childPath.isResolved() && getInfoFromCache(childPath) != null) { dispatchWrite(childPath); } } } --dispatched; if (dispatched == 0) { finished(); } } }