/**
* 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 be.selckin.ws.util.java2php;
import be.selckin.ws.util.java2php.php.PhpClass;
import be.selckin.ws.util.java2php.php.PhpEnum;
import be.selckin.ws.util.java2php.php.PhpProperty;
import be.selckin.ws.util.java2php.php.TypeHint;
import be.selckin.ws.util.java2php.php.PhpType;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.xmlschema.SchemaCollection;
import org.apache.cxf.common.xmlschema.XmlSchemaUtils;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaChoice;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaObject;
import org.apache.ws.commons.schema.XmlSchemaSimpleType;
import org.apache.ws.commons.schema.XmlSchemaType;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class TypesPHPBuilder {
private static final Logger LOG = LogUtils.getL7dLogger(TypesPHPBuilder.class);
private final SchemaCollection xmlSchemaCollection;
private final NameManager nameManager;
private final NamespacePrefixAccumulator prefixAccumulator;
public TypesPHPBuilder(SchemaCollection schemaCollection, NamespacePrefixAccumulator prefixAccumulator, NameManager nameManager) {
this.xmlSchemaCollection = schemaCollection;
this.nameManager = nameManager;
this.prefixAccumulator = prefixAccumulator;
}
public List<PhpType> gatherTypes(XmlSchema schema) {
List<PhpType> phpTypes = new ArrayList<>();
Map<QName, XmlSchemaType> schemaTypes = schema.getSchemaTypes();
for (Map.Entry<QName, XmlSchemaType> e : schemaTypes.entrySet()) {
XmlSchemaType type = e.getValue();
if (type instanceof XmlSchemaComplexType) {
try {
XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
if (!Php.notVeryComplexType(complexType) && complexType.getName() != null)
phpTypes.add(createComplexType(schema, complexType));
} catch (UnsupportedConstruct usc) {
throw new RuntimeException("unsupported", usc);
}
} else if (type instanceof XmlSchemaSimpleType) {
XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) type;
if (XmlSchemaUtils.isEumeration(simpleType)) {
phpTypes.add(new PhpEnum(
simpleType.getQName(),
nameManager.getPhpNamespace(simpleType.getQName()),
nameManager.getPhpClassName(simpleType.getQName()),
XmlSchemaUtils.enumeratorValues(simpleType)
));
}
}
}
for (Map.Entry<QName, XmlSchemaElement> e : schema.getElements().entrySet()) {
XmlSchemaElement element = e.getValue();
try {
if (element.getSchemaTypeName() == null && element.getSchemaType() == null) {
LOG.warning("ELEMENT_MISSING_TYPE " + element.getQName() + " " + element.getSchemaTypeName() + " " + schema.getTargetNamespace());
continue;
}
XmlSchemaType type;
if (element.getSchemaType() != null) {
type = element.getSchemaType();
} else {
type = schema.getTypeByName(element.getSchemaTypeName());
}
if (!(type instanceof XmlSchemaComplexType)) {
continue;
}
XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
if (!Php.notVeryComplexType(complexType) && complexType.getName() != null)
createComplexType(schema, complexType);
} catch (UnsupportedConstruct usc) {
throw new RuntimeException("unsupported", usc);
}
}
return phpTypes;
}
private PhpClass createComplexType(XmlSchema xmlSchema, XmlSchemaComplexType complexType) {
QName qName = complexType.getQName();
List<PhpProperty> properties = new ArrayList<>();
for (XmlSchemaObject thing : XmlSchemaUtils.getContentElements(complexType, xmlSchemaCollection)) {
if (thing instanceof org.apache.ws.commons.schema.XmlSchemaChoice) {
XmlSchemaChoice choice = (XmlSchemaChoice) thing;
for (XmlSchemaObject xmlSchemaObject : choice.getItems()) {
ParticleInfo info = ParticleInfo.forLocalItem(xmlSchemaObject, xmlSchema, xmlSchemaCollection, prefixAccumulator, qName);
PhpProperty orig = createProperty(info);
properties.add(
new PhpProperty(
orig.getName(), new TypeHint(true, orig.getTypeHint().getName()), "null", Arrays.<String>asList(), false,
info.getType().getQName().getNamespaceURI()
)
);
}
// Only sort these, others are returned in jaxb order
Collections.sort(properties, new Comparator<PhpProperty>() {
@Override
public int compare(PhpProperty o1, PhpProperty o2) {
return o1.getName().compareTo(o2.getName());
}
});
} else {
properties.add(createProperty(ParticleInfo.forLocalItem(thing, xmlSchema, xmlSchemaCollection, prefixAccumulator, qName)));
}
}
return new PhpClass(qName, nameManager.getPhpNamespace(qName), nameManager.getPhpClassName(qName), properties);
}
private PhpProperty createProperty(ParticleInfo itemInfo) {
List<String> comments = new ArrayList<>();
String initialValue = "null";
if (itemInfo.isAnyType())
comments.add("- xs:any");
else if (itemInfo.getType() != null)
comments.add("- type: " + itemInfo.getType().getQName());
if (itemInfo.isArray()) {
comments.add("- array");
initialValue = "array()";
}
TypeHint typeHint;
if (itemInfo.getType() instanceof XmlSchemaComplexType && itemInfo.getType().isTopLevel()) {
typeHint = new TypeHint(itemInfo.isArray(), nameManager.getAbsolutePhpClassName(itemInfo.getType().getQName()));
} else {
typeHint = new TypeHint(itemInfo.isArray()); // primitive
}
if (itemInfo.isNillable())
comments.add("- nillable");
if (itemInfo.isOptional())
comments.add("- optional");
else
comments.add("- required");
return new PhpProperty(itemInfo.getXmlName(), typeHint, initialValue, comments, !itemInfo.isOptional());
}
}