/*
* This file is protected by Copyright. Please refer to the COPYRIGHT file
* distributed with this source distribution.
*
* This file is part of REDHAWK core.
*
* REDHAWK core 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.
*
* REDHAWK core 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 this program. If not, see http://www.gnu.org/licenses/.
*/
package org.ossie.properties;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import CF.DataType;
import CF.PropertiesHelper;
public abstract class StructDef {
private Map<String, IProperty> elements;
public StructDef() {
}
public Map<String, IProperty> getElementsMap() {
if (this.elements == null) {
this.elements = new LinkedHashMap<String, IProperty>();
initFields();
}
return this.elements;
}
private void initFields() {
final List<Field> allFields = StructDef.getAllFields(new ArrayList<Field>(), getClass());
for (final Field field : allFields) {
try {
if (IProperty.class.isAssignableFrom(field.getType())) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
// Skip uninitialized fields, which can happen with classes derived
// from concrete subclasses of StructDef (such as the FRONTEND
// tuner status property)
IProperty property = (IProperty) field.get(this);
if (property != null) {
addElement(property);
}
}
} catch (final IllegalArgumentException e) {
e.printStackTrace();
} catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}
private static List<Field> getAllFields(final List<Field> fields, final Class< ? > type) {
for (final Field field : type.getDeclaredFields()) {
fields.add(field);
}
if (type.getSuperclass() != null) {
StructDef.getAllFields(fields, type.getSuperclass());
}
return fields;
}
protected void addElement(final IProperty element) {
getElementsMap().put(element.getId(), element);
}
public boolean equals(final Object item) {
if (!(item instanceof StructDef)) {
return false;
}
StructDef tmp = (StructDef)item;
for (final IProperty prop : this.getElements()) {
Any tmp_prop = tmp.getElement(prop.getId()).toAny();
if (tmp_prop == null) {
return false;
}
if (!prop.toAny().equal(tmp_prop)) {
return false;
}
}
return true;
}
public IProperty[] getElements() {
return getElementsMap().values().toArray(new IProperty[this.getElementsMap().size()]);
}
public IProperty getElement(final String id) {
return getElementsMap().get(id);
}
public Any toAny() {
Any retVal = ORB.init().create_any();
DataType[] props = new DataType[this.getElementsMap().size()];
int ii = 0;
for (IProperty prop : this.getElementsMap().values()) {
props[ii++] = new DataType(prop.getId(), prop.toAny());
}
PropertiesHelper.insert(retVal, props);
return retVal;
}
public void fromAny(Any any) {
if (!any.type().equivalent(PropertiesHelper.type())) {
throw new IllegalArgumentException("Invalid Any type for struct");
}
for (final DataType prop : PropertiesHelper.extract(any)) {
IProperty field = this.getElement(prop.id);
// Ignore unknown fields
if (field != null) {
field.fromAny(prop.value);
}
}
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer();
sb.append("StructDef:");
sb.append(super.toString());
sb.append(this.getElementsMap());
return sb.toString();
}
public String getId() {
// Ideally, this would be an abstract method; however, since there are
// existing Java components whose structs do not override this method,
// return an empty string to avoid breaking source compatibility.
return "";
}
};