package com.intellij.flex.uiDesigner.mxml; import com.intellij.flex.uiDesigner.AssetCounter; import com.intellij.flex.uiDesigner.io.*; import com.intellij.javascript.flex.FlexMxmlLanguageAttributeNames; import org.jetbrains.annotations.Nullable; final class BaseWriter extends PrimitiveWriter { private static final int EMPTY_CLASS_OR_PROPERTY_NAME = 0; final int ARRAY; final int P_FUD_RANGE_ID; private boolean stringWriterFinished; private final int startPosition; private final BlockDataOutputStream blockOut; private final Scope rootScope = new Scope(); final NullContext nullContext; private final AssetCounter assetCounter; public BaseWriter(PrimitiveAmfOutputStream out, AssetCounter assetCounter) { super(out, new StringRegistry.StringWriter()); blockOut = out.getBlockOut(); this.assetCounter = assetCounter; ARRAY = getNameReference("array"); P_FUD_RANGE_ID = getNameReference("$fud_r"); assert blockOut.getLastMarker() == null; startPosition = out.size(); nullContext = new NullContext(rootScope); } public AssetCounter getAssetCounter() { return assetCounter; } public PrimitiveAmfOutputStream getOut() { return out; } public BlockDataOutputStream getBlockOut() { return blockOut; } public int getPreallocatedId() { return nullContext.id; } public boolean isIdPreallocated() { return nullContext.getId() != -1; } public StaticObjectContext createStaticContext(@Nullable Context parentContext, int referencePosition) { if (parentContext == null || parentContext.getBackSibling() == null) { // StaticInstanceReferenceInDeferredParentInstance points to DeferredParentInstance by id in root scope return new StaticObjectContext(referencePosition, out, nullContext.getId(), parentContext instanceof InnerComponentContext || (parentContext instanceof StaticObjectContext && parentContext.getScope().staticObjectPointToScope) ? parentContext.getScope() : rootScope); } else { return parentContext.getBackSibling().reinitialize(referencePosition, nullContext.getId()); } } public InnerComponentContext createInnerComponentContext(@Nullable MxmlObjectReference objectReference, int id) { return new InnerComponentContext(rootScope, objectReference, id); } void resetAfterMessage() { if (!stringWriterFinished) { stringWriter.rollback(); } } public void endObject() { out.write(EMPTY_CLASS_OR_PROPERTY_NAME); } public int allocateAbsoluteStaticObjectId() { return rootScope.referenceCounter++; } public void writeMessageHeader(ProjectComponentReferenceCounter projectComponentReferenceCounter) { final ByteRange range = blockOut.startRange(); if (projectComponentReferenceCounter.total.isEmpty()) { out.write(Amf3Types.NULL); } else { out.write(projectComponentReferenceCounter.total); } stringWriter.writeTo(out); stringWriterFinished = true; out.writeShort(rootScope.referenceCounter); blockOut.endRange(range); blockOut.insert(startPosition, range); } public void prepend(ByteRange range) { blockOut.insert(startPosition, range); } public int getNameReference(String classOrPropertyName) { return stringWriter.getReference(classOrPropertyName); } public void classOrPropertyName(String classOrPropertyName) { stringWriter.write(classOrPropertyName, out); } public void vectorHeader(String elementType) { out.write(Amf3Types.VECTOR_OBJECT); stringWriter.write(elementType, out); } public void idMxmlProperty(String value) { classOrPropertyName(FlexMxmlLanguageAttributeNames.ID); out.write(AmfExtendedTypes.ID); out.writeAmfUtf(value, false); } public void objectReference(int reference) { out.write(AmfExtendedTypes.OBJECT_REFERENCE); out.writeUInt29(reference); } public void objectReference(Context context) { objectReference(context.getOrAllocateId()); } public void objectHeader(int className) { out.write(AmfExtendedTypes.OBJECT); out.writeUInt29(className); } public void objectHeader(String className) { out.write(AmfExtendedTypes.OBJECT); stringWriter.write(className, out); } public void mxmlObjectHeader(String className) { stringWriter.write(className, out); out.allocateClearShort(); } public void documentFactoryReference(int reference) { out.write(AmfExtendedTypes.DOCUMENT_FACTORY_REFERENCE); out.writeUInt29(reference); } public void documentReference(int reference) { out.write(AmfExtendedTypes.DOCUMENT_REFERENCE); out.writeUInt29(reference); } public void projectClassReference(int reference) { out.write(AmfExtendedTypes.PROJECT_CLASS_REFERENCE); out.writeUInt29(reference); assetCounter.viewCount++; } public void classReference(String className) { out.write(AmfExtendedTypes.CLASS_REFERENCE); classOrPropertyName(className); } public void arrayHeader(int length) { out.write(Amf3Types.ARRAY); out.writeShort(length); } public int arrayHeader() { out.write(Amf3Types.ARRAY); return out.allocateClearShort(); } public BaseWriter newInstance(String className, int argumentsLength, boolean rollbackable) { out.write(ExpressionMessageTypes.NEW); classOrPropertyName(className); out.write((argumentsLength << 1) | (rollbackable ? 1 : 0)); return this; } public BaseWriter referableHeader(int reference) { out.write(AmfExtendedTypes.REFERABLE); out.writeShort(reference + 1); return this; } public int componentFactory(int reference) { out.write(AmfExtendedTypes.COMPONENT_FACTORY); out.writeUInt29(reference + 1); int sizePosition = out.allocateShort(); out.allocateShort(); // object table size return sizePosition; } public int referableHeader() { out.write(AmfExtendedTypes.REFERABLE); return out.allocateClearShort(); } public BaseWriter property(int propertyName) { out.writeUInt29(propertyName); return this; } public BaseWriter property(String propertyName) { classOrPropertyName(propertyName); return this; } public void typeMarker(int typeMarker) { out.write(typeMarker); } }