/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.xsd.builders;
import static org.whole.lang.xsd.mapping.util.MappingStrategyUtils.*;
import java.io.StringWriter;
import java.util.Date;
import java.util.Stack;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.builders.GenericBuilderContext;
import org.whole.lang.builders.GenericEventTrackingBuilder;
import org.whole.lang.builders.IBuilderOperation;
import org.whole.lang.commons.builders.ICommonsBuilder;
import org.whole.lang.commons.reflect.CommonsLanguageKit;
import org.whole.lang.contexts.IBuilderContext;
import org.whole.lang.contexts.IEntityContext;
import org.whole.lang.model.EnumValue;
import org.whole.lang.model.IEntity;
import org.whole.lang.operations.PrettyPrinterOperation;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.templates.ITemplate;
import org.whole.lang.util.DataTypeUtils;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.xml.builders.IXmlBuilder;
import org.whole.lang.xml.reflect.XmlLanguageKit;
/**
* @author Enrico Persiani
*/
public class XsiGeneric2XmlBuilderAdapter extends GenericEventTrackingBuilder {
private IXmlBuilder xb;
private ICommonsBuilder cb;
private IBindingManager bm;
public XsiGeneric2XmlBuilderAdapter(IBuilderOperation targetOperation, EntityDescriptor<?> context, FeatureDescriptor fd) {
super(null, context, fd);
wSetBuilderStrategy(new Xsi2XmlBuilder(context, fd));
xb = (IXmlBuilder) targetOperation.wGetBuilder(XmlLanguageKit.URI);
cb = (ICommonsBuilder) targetOperation.wGetBuilder(CommonsLanguageKit.URI);
bm = BindingManagerFactory.instance.createBindingManager();
}
private enum State {
INITIAL, IN_ATTRIBUTES, IN_ATTRIBUTE, IN_CONTENT, IN_STRUCTURE, UNKNOWN;
}
public class Xsi2XmlBuilder extends GenericBuilderContext {
private Stack<State> states;
public Xsi2XmlBuilder(EntityDescriptor<?> context, FeatureDescriptor fd) {
states = new Stack<State>();
states.push(State.INITIAL);
}
private String getPrefix(EntityDescriptor<?> ed) {
if (!ed.getLanguageKit().getURI().equals(wGetEntityDescriptor().getLanguageKit().getURI()))
setDeferredNamespeceDecl("prefix", "http://uri");
return "prefix"; //TODO get/calculate prefix
}
private void buildQualifiedName(String prefix, String name) {
xb.QualifiedName_();
xb.NameSpace(prefix);
xb.Name(name);
xb._QualifiedName();
}
private void buildNamespeceDecl(String prefix, String uri) {
xb.Attribute_();
buildQualifiedName("xmlns", prefix);
xb.Value(uri);
xb._Attribute();
}
private String deferredPrefix, deferredUri;
private void setDeferredNamespeceDecl(String prefix, String uri) {
deferredPrefix = prefix;
deferredUri = uri;
}
private void buildDeferredNamespeceDecl() {
if (deferredPrefix != null) {
buildNamespeceDecl(deferredPrefix, deferredUri);
deferredUri = deferredPrefix = null;
}
}
private void buildElementName(EntityDescriptor<?> ed, String name) {
//TODO add a strategy to add prefix using elementForm
buildQualifiedName(getPrefix(ed), name);
}
private void buildAttributeName(EntityDescriptor<?> ed, String name) {
//TODO add a strategy to add prefix using attributeForm
xb.Name(name);
}
private void buildComment(String comment) {
xb.Comment_();
xb.CommentText(comment);
xb._Comment();
}
public void wEntity_(EntityDescriptor<?> ed, int initialCapacity) {
wEntity_(ed);
}
public void wEntity(EntityDescriptor<?> ed) {
EntityDescriptor<?> context = wGetEntityDescriptor();
FeatureDescriptor fd = wCurrentGetFeatureDescriptor();
String name;
switch (states.peek()) {
case INITIAL:
name = getElementNCName(context, ed, fd);
if (name != null) {
xb.Element_();
buildElementName(ed, name);
xb.Attributes_();
buildDeferredNamespeceDecl();
xb._Attributes();
xb._Element();
} else {
StringBuilder contents = new StringBuilder();
contents.append("[[unrooted contents]] ");
contents.append(ed.getName());
contents.append(" {}\n");
buildComment(contents.toString());
}
break;
case IN_ATTRIBUTES:
throw new IllegalStateException("not implemented yet");
case IN_CONTENT:
name = getElementNCName(context, ed, fd);
if (name != null) {
xb.Element_();
buildElementName(ed, name);
xb.Attributes_();
buildDeferredNamespeceDecl();
xb._Attributes();
xb._Element();
} else
throw new IllegalStateException("not implemented yet");
break;
case IN_ATTRIBUTE:
case UNKNOWN:
throw new IllegalStateException("illegal mapping");
}
}
public void wEntity_(EntityDescriptor<?> ed) {
EntityDescriptor<?> context = wGetEntityDescriptor();
FeatureDescriptor fd = wCurrentGetFeatureDescriptor();
String name;
switch (states.peek()) {
case INITIAL:
if ((name = getElementNCName(context, ed, fd)) != null) {
xb.Element_();
buildElementName(ed, name);
xb.Attributes_();
buildDeferredNamespeceDecl();
states.push(State.IN_ATTRIBUTES); // INITIAL -> IN_ATTRIBUTES
} else {
states.push(State.UNKNOWN); // INITIAL -> UNKNOWN
wBuildEntity_(ed);
}
break;
case IN_ATTRIBUTES:
name = getAttributeNCName(context, ed, fd);
if (name != null) {
xb.Attribute_();
buildAttributeName(ed, name);
states.push(State.IN_ATTRIBUTE); // IN_ATTRIBUTES -> IN_ATTRIBUTE
wBuildEntity_(ed);
} else if ((name = getElementNCName(context, ed, fd)) != null) {
xb._Attributes();
xb.Content_();
states.pop(); // IN_ATTRIBUTES -> IN_CONTENT
states.push(State.IN_CONTENT);
} else
throw new IllegalStateException("not implemented yet");
break;
case IN_ATTRIBUTE:
throw new IllegalStateException("not implemented yet");
case IN_CONTENT:
if ((name = getElementNCName(context, ed, fd)) != null) {
xb.Element_();
buildElementName(ed, name);
xb.Attributes_();
buildDeferredNamespeceDecl();
states.push(State.IN_ATTRIBUTES); // INITIAL -> IN_ATTRIBUTES
} else {
StringBuilder contents = new StringBuilder();
contents.append("[[unrooted contents]] ");
contents.append(ed.getName());
contents.append(" {}");
buildComment(contents.toString());
}
break;
case UNKNOWN:
throw new IllegalStateException("illegal mapping");
}
}
public void _wEntity(EntityDescriptor<?> ed) {
EntityDescriptor<?> context = wGetEntityDescriptor();
FeatureDescriptor fd = wCurrentGetFeatureDescriptor();
String name;
IEntity entity;
switch (states.peek()) {
case INITIAL:
name = getElementNCName(context, ed, fd);
if (name != null) {
xb.Element_();
buildElementName(ed, name);
xb.Attributes_();
buildDeferredNamespeceDecl();
states.push(State.IN_ATTRIBUTES); // INITIAL -> IN_ATTRIBUTES
} else {
StringBuilder contents = new StringBuilder();
contents.append("[[unrooted contents]] ");
contents.append(ed.getName());
contents.append(" {}");
buildComment(contents.toString());
}
break;
case IN_ATTRIBUTES:
name = getAttributeNCName(context, ed, fd);
if (name != null) {
xb.Attribute_();
buildAttributeName(ed, name);
states.push(State.IN_ATTRIBUTE); // IN_ATTRIBUTES -> IN_ATTRIBUTE
wBuildEntity_(ed);
} else {
}
break;
case IN_ATTRIBUTE:
entity = _wBuildEntity(ed);
if (EntityUtils.isComposite(entity)) {
StringBuilder value = new StringBuilder();
for (int i=0, size=entity.wSize(); i< size; i++) {
if (i>0)
value.append(' ');
IEntity child = entity.wGet(i);
if (EntityUtils.isData(child))
value.append(DataTypeUtils.getAsPersistenceString(child));
else
throw new IllegalStateException("not implemented yet");
}
xb.Value(value.toString());
xb._Attribute();
} else
throw new IllegalStateException("not implemented yet");
states.pop(); // IN_ATTRIBUTE -> [PREVIOUS STATE]
assert states.peek() == State.IN_ATTRIBUTES;
break;
case IN_CONTENT:
throw new IllegalStateException("not implemented yet");
case UNKNOWN:
entity = _wBuildEntity(ed);
StringWriter contents = new StringWriter();
contents.append("[[unrooted contents]] ");
contents.append(ed.getName());
contents.append(" {\n");
for (int i=0, size=entity.wSize(); i<size; i++)
PrettyPrinterOperation.prettyPrint(entity.wGet(i), contents);
contents.append("\n}\n");
buildComment(contents.toString());
states.pop(); // UNKNOWN -> [PREVIOUS STATE]
}
}
public void wEntity(EntityDescriptor<?> ed, boolean value) {
}
public void wEntity(EntityDescriptor<?> ed, byte value) {
}
public void wEntity(EntityDescriptor<?> ed, char value) {
}
public void wEntity(EntityDescriptor<?> ed, double value) {
}
public void wEntity(EntityDescriptor<?> ed, float value) {
}
public void wEntity(EntityDescriptor<?> ed, int value) {
}
public void wEntity(EntityDescriptor<?> ed, long value) {
}
public void wEntity(EntityDescriptor<?> ed, short value) {
}
public void wEntity(EntityDescriptor<?> ed, String value) {
}
public void wEntity(EntityDescriptor<?> ed, Date value) {
}
public void wEntity(EntityDescriptor<?> ed, EnumValue value) {
}
public void wEntity(EntityDescriptor<?> ed, Object value) {
}
public void wSetBuilderContext(IBuilderContext context) {
}
public void wSetEntityContext(IEntityContext context) {
}
public void wDefault() {
throw new UnsupportedOperationException();
}
public void wEntity() {
throw new UnsupportedOperationException();
}
public void wEntity_() {
throw new UnsupportedOperationException();
}
public void _wEntity() {
throw new UnsupportedOperationException();
}
public void wFeature(int index) {
throw new UnsupportedOperationException();
}
public void wFeature(FeatureDescriptor feature) {
throw new UnsupportedOperationException();
}
public void wFeature(ITemplate template) {
throw new UnsupportedOperationException();
}
}
}