private Object read( DataInput objBuffer, Type propertyType, boolean array, UnrealPackageReadOnly.ExportEntry arrayInner, String structName, UnrealPackageReadOnly up) throws IOException { switch (propertyType) { case NONE: return null; case BYTE: return objBuffer.readUnsignedByte(); case INT: return objBuffer.readInt(); case BOOL: return array; case FLOAT: return objBuffer.readFloat(); case OBJECT: return objBuffer.readCompactInt(); case NAME: return objBuffer.readCompactInt(); case ARRAY: int arraySize = objBuffer.readCompactInt(); List<Object> arrayList = new ArrayList<>(arraySize); String a = arrayInner.getObjectClass().getObjectName().getName(); Property f = unrealClassLoader.getProperty(arrayInner.getObjectFullName()); array = false; arrayInner = null; structName = null; propertyType = Type.valueOf(a.replace("Property", "").toUpperCase()); if (propertyType == Type.STRUCT) { StructProperty structProperty = (StructProperty) f; structName = structProperty.getStructType().getObjectFullName(); } if (propertyType == Type.ARRAY) { array = true; ArrayProperty arrayProperty = (ArrayProperty) f; arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); } for (int i = 0; i < arraySize; i++) { arrayList.add(read(objBuffer, propertyType, array, arrayInner, structName, up)); } return arrayList; case STRUCT: return readStruct(objBuffer, structName, up); /*case VECTOR: return readStruct(objBuffer, "Vector", up); case ROTATOR: return readStruct(objBuffer, "Rotator", up);*/ case STR: return objBuffer.readLine(); default: throw new IllegalStateException("Unk type(" + structName + "): " + propertyType); } }
@Test public void testArrayResponse() { Swagger swagger = new Swagger(); ArrayProperty schema = new ArrayProperty(); schema.setItems(new ObjectProperty().property("name", new StringProperty())); swagger.path( "/foo/baz", new Path() .get( new Operation() .response( 200, new Response() .vendorExtension("x-foo", "bar") .description("it works!") .schema(schema)))); new InlineModelResolver().flatten(swagger); Response response = swagger.getPaths().get("/foo/baz").getGet().getResponses().get("200"); assertTrue(response.getSchema() instanceof ArrayProperty); ArrayProperty am = (ArrayProperty) response.getSchema(); Property items = am.getItems(); assertTrue(items instanceof ObjectProperty); ObjectProperty op = (ObjectProperty) items; Property name = op.getProperties().get("name"); assertTrue(name instanceof StringProperty); }
@Override public String getTypeDeclaration(Property p) { if (p instanceof ArrayProperty) { ArrayProperty ap = (ArrayProperty) p; Property inner = ap.getItems(); String innerType = getSwaggerType(inner); String innerTypeDeclaration = getTypeDeclaration(inner); if (innerTypeDeclaration.endsWith("*")) { innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1); } // In this codition, type of property p is array of primitive, // return container type with pointer, e.g. `NSArray* /* NSString */' if (languageSpecificPrimitives.contains(innerType)) { return getSwaggerType(p) + "*" + " /* " + innerTypeDeclaration + " */"; } // In this codition, type of property p is array of model, // return container type combine inner type with pointer, e.g. `NSArray<SWGTag>*' else { return getSwaggerType(p) + "<" + innerTypeDeclaration + ">*"; } } else if (p instanceof MapProperty) { MapProperty mp = (MapProperty) p; Property inner = mp.getAdditionalProperties(); String innerTypeDeclaration = getTypeDeclaration(inner); if (innerTypeDeclaration.endsWith("*")) { innerTypeDeclaration = innerTypeDeclaration.substring(0, innerTypeDeclaration.length() - 1); } return getSwaggerType(p) + "* /* NSString, " + innerTypeDeclaration + " */"; } else { String swaggerType = getSwaggerType(p); // In this codition, type of p is objective-c primitive type, e.g. `NSSNumber', // return type of p with pointer, e.g. `NSNumber*' if (languageSpecificPrimitives.contains(swaggerType) && foundationClasses.contains(swaggerType)) { return swaggerType + "*"; } // In this codition, type of p is c primitive type, e.g. `bool', // return type of p, e.g. `bool' else if (languageSpecificPrimitives.contains(swaggerType)) { return swaggerType; } // In this codition, type of p is objective-c object type, e.g. `SWGPet', // return type of p with pointer, e.g. `SWGPet*' else { return swaggerType + "*"; } } }
@Override public String getTypeDeclaration(Property p) { if (p instanceof ArrayProperty) { ArrayProperty ap = (ArrayProperty) p; Property inner = ap.getItems(); return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; } else if (p instanceof MapProperty) { MapProperty mp = (MapProperty) p; Property inner = mp.getAdditionalProperties(); return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">"; } return super.getTypeDeclaration(p); }
@Override public String toInstantiationType(Property p) { if (p instanceof MapProperty) { MapProperty ap = (MapProperty) p; String inner = getSwaggerType(ap.getAdditionalProperties()); return instantiationTypes.get("map"); } else if (p instanceof ArrayProperty) { ArrayProperty ap = (ArrayProperty) p; String inner = getSwaggerType(ap.getItems()); return instantiationTypes.get("array"); } else { return null; } }
@Override public String getTypeDeclaration(Property p) { if (p instanceof ArrayProperty) { ArrayProperty ap = (ArrayProperty) p; Property inner = ap.getItems(); return getTypeDeclaration(inner) + "[]"; } else if (p instanceof MapProperty) { MapProperty mp = (MapProperty) p; Property inner = mp.getAdditionalProperties(); return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; } else if (p instanceof RefProperty) { String type = super.getTypeDeclaration(p); return (!languageSpecificPrimitives.contains(type)) ? "\\" + modelPackage + "\\" + type : type; } return super.getTypeDeclaration(p); }
@Test public void resolveInlineArrayResponse() throws Exception { Swagger swagger = new Swagger(); swagger.path( "/foo/baz", new Path() .get( new Operation() .response( 200, new Response() .vendorExtension("x-foo", "bar") .description("it works!") .schema( new ArrayProperty() .items( new ObjectProperty() .property("name", new StringProperty())))))); new InlineModelResolver().flatten(swagger); Response response = swagger.getPaths().get("/foo/baz").getGet().getResponses().get("200"); assertNotNull(response); assertNotNull(response.getSchema()); Property responseProperty = response.getSchema(); // no need to flatten more assertTrue(responseProperty instanceof ArrayProperty); ArrayProperty ap = (ArrayProperty) responseProperty; Property p = ap.getItems(); assertNotNull(p); ObjectProperty innerModel = (ObjectProperty) p; assertTrue(innerModel.getProperties().size() == 1); assertNotNull(innerModel.getProperties().get("name")); }
@Override public String toDefaultValue(Property p) { if (p instanceof ArrayProperty) { final ArrayProperty ap = (ArrayProperty) p; final String pattern; if (fullJavaUtil) { pattern = "new java.util.ArrayList<%s>()"; } else { pattern = "new ArrayList<%s>()"; } return String.format(pattern, getTypeDeclaration(ap.getItems())); } else if (p instanceof MapProperty) { final MapProperty ap = (MapProperty) p; final String pattern; if (fullJavaUtil) { pattern = "new java.util.HashMap<String, %s>()"; } else { pattern = "new HashMap<String, %s>()"; } return String.format(pattern, getTypeDeclaration(ap.getAdditionalProperties())); } else if (p instanceof IntegerProperty) { IntegerProperty dp = (IntegerProperty) p; if (dp.getDefault() != null) { return dp.getDefault().toString(); } return "null"; } else if (p instanceof LongProperty) { LongProperty dp = (LongProperty) p; if (dp.getDefault() != null) { return dp.getDefault().toString() + "l"; } return "null"; } else if (p instanceof DoubleProperty) { DoubleProperty dp = (DoubleProperty) p; if (dp.getDefault() != null) { return dp.getDefault().toString() + "d"; } return "null"; } else if (p instanceof FloatProperty) { FloatProperty dp = (FloatProperty) p; if (dp.getDefault() != null) { return dp.getDefault().toString() + "f"; } return "null"; } else if (p instanceof BooleanProperty) { BooleanProperty bp = (BooleanProperty) p; if (bp.getDefault() != null) { return bp.getDefault().toString(); } return "null"; } else if (p instanceof StringProperty) { StringProperty sp = (StringProperty) p; if (sp.getDefault() != null) { String _default = sp.getDefault(); if (sp.getEnum() == null) { return "\"" + escapeText(_default) + "\""; } else { // convert to enum var name later in postProcessModels return _default; } } return "null"; } return super.toDefaultValue(p); }
public List<L2Property> readProperties( DataInput dataInput, String objClass, UnrealPackageReadOnly up) throws UnrealException { List<L2Property> properties = new ArrayList<>(); List<Property> classTemplate = unrealClassLoader.getStructProperties(objClass); Collections.reverse(classTemplate); try { String name; while (!(name = up.getNameTable().get(dataInput.readCompactInt()).getName()).equals("None")) { int info = dataInput.readUnsignedByte(); Type propertyType = Type.values()[info & 0b1111]; // TODO int sizeType = (info >> 4) & 0b111; boolean array = info >> 7 == 1; String structName = propertyType.equals(Type.STRUCT) ? up.getNameTable().get(dataInput.readCompactInt()).getName() : null; int size = readPropertySize(sizeType, dataInput); int arrayIndex = array && !propertyType.equals(Type.BOOL) ? dataInput.readCompactInt() : 0; byte[] objBytes = new byte[size]; dataInput.readFully(objBytes); final String n = name; PropertiesUtil.getAt(properties, n); L2Property property = PropertiesUtil.getAt(properties, n); if (property == null) { Property template = classTemplate .stream() .filter(pt -> pt.getEntry().getObjectName().getName().equalsIgnoreCase((n))) .findAny() .orElse(null); if (template == null) throw new UnrealException(objClass + ": Property template not found: " + name); property = new L2Property(template, up); properties.add(property); } if (structName != null && !"Vector".equals(structName) && !"Rotator".equals(structName) && !"Color".equals(structName)) { StructProperty structProperty = (StructProperty) property.getTemplate(); structName = structProperty.getStructType().getObjectFullName(); } UnrealPackageReadOnly.ExportEntry arrayInner = null; if (propertyType.equals(Type.ARRAY)) { ArrayProperty arrayProperty = (ArrayProperty) property.getTemplate(); arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); } DataInput objBuffer = new DataInputStream(new ByteArrayInputStream(objBytes), dataInput.getCharset()); property.putAt( arrayIndex, read( objBuffer, propertyType, array, arrayInner, structName, up, objClass, property.getName())); property.setType(propertyType); } } catch (IOException e) { throw new UnrealException(e); } return properties; }
private void write( DataOutput objBuffer, Property template, Object obj, AtomicBoolean array, AtomicReference<String> structName, AtomicReference<Type> type, UnrealPackageReadOnly up) throws IOException { if (template instanceof ByteProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [BYTE]"); objBuffer.writeByte((Integer) obj); } else if (template instanceof IntProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [INT]"); objBuffer.writeInt((Integer) obj); } else if (template instanceof BoolProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [BOOL]"); array.set((Boolean) obj); } else if (template instanceof FloatProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [FLOAT]"); objBuffer.writeFloat((Float) obj); } else if (template instanceof ObjectProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [OBJ]"); objBuffer.writeCompactInt((Integer) obj); } else if (template instanceof NameProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [NAME]"); objBuffer.writeCompactInt((Integer) obj); } else if (template instanceof ArrayProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [ARRAY]"); ArrayProperty arrayProperty = (ArrayProperty) template; List<Object> arrayList = (List<Object>) obj; objBuffer.writeCompactInt(arrayList.size()); UnrealPackageReadOnly.ExportEntry arrayInner = (UnrealPackageReadOnly.ExportEntry) arrayProperty.getInner(); String a = arrayInner.getObjectClass().getObjectName().getName(); try { Class<? extends Property> pc = Class.forName("acmi.l2.clientmod.unreal." + a).asSubclass(Property.class); Property f = pc.getConstructor( ByteBuffer.class, UnrealPackageReadOnly.ExportEntry.class, PropertiesUtil.class) .newInstance( ByteBuffer.wrap(arrayInner.getObjectRawDataExternally()) .order(ByteOrder.LITTLE_ENDIAN), arrayInner, this); for (Object arrayObj : arrayList) { write( objBuffer, f, arrayObj, new AtomicBoolean(), new AtomicReference<>(), new AtomicReference<>(), up); } } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } else if (template instanceof StructProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [STRUCT]"); StructProperty structProperty = (StructProperty) template; structName.set(structProperty.getStructType().getObjectName().getName()); writeStruct(objBuffer, structName.get(), up, (List<L2Property>) obj); // if (false) { //Not used in L2? // switch (structName.get()) { // case "Vector": // type.set(Type.VECTOR); // break; // case "Rotator": // type.set(Type.ROTATOR); // break; // } // } } else if (template instanceof StrProperty) { System.out.println(template.getEntry().getObjectInnerFullName() + " [STR]"); objBuffer.writeLine((String) obj); } else { throw new UnsupportedOperationException( template.getClass().getSimpleName() + " serialization not implemented"); } }