Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

try to fix duplicated fields in attribute and child element #96

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions xstream/src/java/com/thoughtworks/xstream/XStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ public void aliasPackage(final String name, final String pkgName) {
}
packageAliasingMapper.addPackageAlias(name, pkgName);
}

/**
* Create an alias for a field name.
*
Expand All @@ -1395,10 +1395,24 @@ public void aliasPackage(final String name, final String pkgName) {
* @throws InitializationException if no {@link FieldAliasingMapper} is available
*/
public void aliasField(final String alias, final Class<?> definedIn, final String fieldName) {
aliasField(alias, false, definedIn, fieldName);
}


/**
* Create an alias for a field name.
*
* @param alias the alias itself
* @param isAttr is attribute or not
* @param definedIn the type that declares the field
* @param fieldName the name of the field
* @throws InitializationException if no {@link FieldAliasingMapper} is available
*/
public void aliasField(final String alias, final boolean isAttr, final Class<?> definedIn, final String fieldName) {
if (fieldAliasingMapper == null) {
throw new InitializationException("No " + FieldAliasingMapper.class.getName() + " available");
}
fieldAliasingMapper.addFieldAlias(alias, definedIn, fieldName);
fieldAliasingMapper.addFieldAlias(alias, isAttr, definedIn, fieldName);
}

/**
Expand Down Expand Up @@ -1442,7 +1456,7 @@ public void aliasSystemAttribute(final String alias, final String systemAttribut
* @since 1.2.2
*/
public void aliasAttribute(final Class<?> definedIn, final String attributeName, final String alias) {
aliasField(alias, definedIn, attributeName);
aliasField(alias, true, definedIn, attributeName);
useAttributeFor(definedIn, attributeName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,10 @@ public Object unmarshal(final HierarchicalStreamReader reader, final Unmarshalli
}

public Object doUnmarshal(final Object result, final HierarchicalStreamReader reader,
final UnmarshallingContext context) {
final UnmarshallingContext context) {

final Class<?> resultType = result.getClass();

@SuppressWarnings("serial")
final Set<FastField> seenFields = new HashSet<FastField>() {
@Override
Expand All @@ -297,7 +299,8 @@ public boolean add(final FastField e) {
while (it.hasNext()) {
final String attrAlias = it.next();
// TODO: realMember should return FastField
final String attrName = mapper.realMember(resultType, mapper.attributeForAlias(attrAlias));
String attr1 = mapper.attributeForAlias(attrAlias);
final String attrName = mapper.realMember(resultType, attr1, true);
final Field field = reflectionProvider.getFieldOrNull(resultType, attrName);
if (field != null && shouldUnmarshalField(field)) {
final Class<?> classDefiningField = field.getDeclaringClass();
Expand Down
68 changes: 44 additions & 24 deletions xstream/src/java/com/thoughtworks/xstream/core/util/FastField.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@
public final class FastField {
private final String name;
private final String declaringClass;
private final boolean isAttribute;

public FastField(final String definedIn, final String name) {
this.name = name;
declaringClass = definedIn;
this.isAttribute = false;
}

public FastField(final String definedIn, final String alias, boolean isAttribute) {
this.name = alias;
declaringClass = definedIn;
this.isAttribute = isAttribute;
}

public FastField(final Class<?> definedIn, final String name) {
this(definedIn == null ? null : definedIn.getName(), name);
}
Expand All @@ -31,33 +39,45 @@ public String getDeclaringClass() {
return declaringClass;
}

@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof FastField) {
final FastField field = (FastField)obj;
if (declaringClass == null && field.declaringClass != null
|| declaringClass != null && field.declaringClass == null) {
return false;
}
return name.equals(field.getName())
&& (declaringClass == null || declaringClass.equals(field.getDeclaringClass()));
}
return false;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FastField other = (FastField) obj;
if (declaringClass == null) {
if (other.declaringClass != null)
return false;
}
else if (!declaringClass.equals(other.declaringClass))
return false;
if (isAttribute != other.isAttribute)
return false;
if (name == null) {
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
return true;
}

@Override
public int hashCode() {
return name.hashCode() ^ (declaringClass == null ? 0 : declaringClass.hashCode());
}

public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
result = prime * result + (isAttribute ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public String toString() {
return (declaringClass == null ? "" : declaringClass + ".") + name;
return (declaringClass == null ? "" : declaringClass + ".") + name + " " + isAttribute ;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ public String realMember(final Class<?> type, final String serialized) {
}
return super.realMember(type, serialized);
}

public String realMember(final Class<?> type, final String serialized, boolean attrOrNot) {
if (!locked) {
processAnnotation(type);
}
return super.realMember(type, serialized, attrOrNot);
}


@Override
public String serializedClass(final Class<?> type) {
Expand Down Expand Up @@ -343,7 +351,13 @@ private void processFieldAliasAnnotation(final Field field) {
if (fieldAliasingMapper == null) {
throw new InitializationException("No " + FieldAliasingMapper.class.getName() + " available");
}
fieldAliasingMapper.addFieldAlias(aliasAnnotation.value(), field.getDeclaringClass(), field.getName());

boolean isAttr = false;
if(field.getAnnotation(XStreamAsAttribute.class)!=null) {
isAttr = true;
}

fieldAliasingMapper.addFieldAlias(aliasAnnotation.value(), isAttr, field.getDeclaringClass(), field.getName());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ public String realMember(final Class<?> type, final String serialized) {
return serialized;
}

@Override
public String realMember(final Class<?> type, final String serialized, boolean attributeOrNot) {
return serialized;
}

/**
* @deprecated As of 1.3, use {@link #getConverterFromAttribute(Class, String, Class)}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ public FieldAliasingMapper(final Mapper wrapped) {
elementIgnoringMapper = lookupMapperOfType(ElementIgnoringMapper.class);
}

public void addFieldAlias(final String alias, final Class<?> type, final String fieldName) {
public void addFieldAlias(final String alias, boolean isAttr, final Class<?> type, final String fieldName) {
fieldToAliasMap.put(key(type, fieldName), alias);
aliasToFieldMap.put(key(type, alias), fieldName);
aliasToFieldMap.put(new FastField(type.getName(), alias, isAttr), fieldName);
}

/**
Expand Down
8 changes: 8 additions & 0 deletions xstream/src/java/com/thoughtworks/xstream/mapper/Mapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,18 @@ class Null {}
*/
String serializedMember(Class<?> type, String memberName);


/**
* How a serialized member representation should be mapped back to a real member.
*/
String realMember(Class<?> type, String serialized);

/**
* How a serialized member representation should be mapped back to a real member.
* @param attributeOrNot: is attribute or child element
*/
String realMember(Class<?> type, String serialized, boolean attributeOrNot);


/**
* Whether this type is a simple immutable value (int, boolean, String, URL, etc). Immutable types will be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ public String serializedMember(final Class<?> type, final String memberName) {
public String realMember(final Class<?> type, final String serialized) {
return realMemberMapper.realMember(type, serialized);
}

@Override
public String realMember(final Class<?> type, final String serialized, boolean attrOrNot) {
return realMemberMapper.realMember(type, serialized, attrOrNot);
}

@Override
public boolean isImmutableValueType(final Class<?> type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.thoughtworks.xstream.mapper.newtest1;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

@XStreamAlias("delete")
public class Delete {
@XStreamAlias("id")
@XStreamAsAttribute
public String id;

@XStreamAlias("parameterType")
@XStreamAsAttribute
public String parameterType;


public String getParameterType() {
return parameterType;
}

public void setParameterType(String parameterType) {
this.parameterType = parameterType;
}

}
34 changes: 34 additions & 0 deletions xstream/src/test/com/thoughtworks/xstream/mapper/newtest1/Id.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.thoughtworks.xstream.mapper.newtest1;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

@XStreamAlias("id")
public class Id {
@XStreamAlias("column")
@XStreamAsAttribute
public String column;

@XStreamAlias("property")
@XStreamAsAttribute
public String property;

public String toString() {
return this.column + " " + this.property;
}


public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.thoughtworks.xstream.mapper.newtest1;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

@XStreamAlias("insert")
public class Insert {
@XStreamAlias("id")
@XStreamAsAttribute
public String id;

@XStreamAlias("parameterType")
@XStreamAsAttribute
public String parameterType;


public String getParameterType() {
return parameterType;
}

public void setParameterType(String parameterType) {
this.parameterType = parameterType;
}

}
Loading