/* * Copyright (c) 2008-2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.common.schema; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import com.emc.storageos.db.common.DbSchemaScannerInterceptor; import com.google.common.base.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.impl.DataObjectType; import com.emc.storageos.db.client.model.Cf; public class DbSchema implements SchemaObject { private static final Logger log = LoggerFactory.getLogger(DbSchema.class); private RuntimeType runtimeType; // the following field is used in unmarshalled instances private String type; // the following fields are used to distinguish instances private String name; private List<FieldInfo> fields = new ArrayList<FieldInfo>(); private Annotations annotations; public DbSchema() { } public DbSchema(Class clazz) { this(clazz, null); } public DbSchema(Class clazz, DbSchemaScannerInterceptor scannerInterceptor) { runtimeType = new RuntimeType(); runtimeType.setCfClass(clazz); this.name = clazz.getSimpleName(); Cf cfAnnotation = (Cf) clazz.getAnnotation(Cf.class); if (cfAnnotation != null) { this.name = cfAnnotation.value(); } BeanInfo bInfo; try { bInfo = Introspector.getBeanInfo(clazz); } catch (IntrospectionException ex) { log.error("Failed to get bean info:", ex); throw new IllegalStateException(ex.getMessage()); } PropertyDescriptor[] pds = bInfo.getPropertyDescriptors(); for (int i = 0; i < pds.length; i++) { PropertyDescriptor pd = pds[i]; if (!DataObjectType.isColumnField(bInfo.getBeanDescriptor().getBeanClass().getName(), pd)) { continue; } pd.setShortDescription(this.name + "." + pd.getShortDescription()); this.fields.add(new FieldInfo(runtimeType, pd, this, scannerInterceptor)); } annotations = new Annotations(runtimeType, clazz.getDeclaredAnnotations(), this, scannerInterceptor); } @XmlAttribute public String getType() { if (runtimeType == null) { return type; } return runtimeType.getCfClass().getCanonicalName(); } public void setType(String type) { this.type = type; } @Key @XmlAttribute public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElement public Annotations getAnnotations() { return annotations; } public void setAnnotations(Annotations annotations) { this.annotations = annotations; } @XmlElementWrapper(name = "fields") @XmlElement(name = "field") public List<FieldInfo> getFields() { return fields; } public void setFields(List<FieldInfo> fields) { this.fields = fields; } @Override public boolean equals(Object o) { if (!(o instanceof DbSchema)) { return false; } DbSchema schema = (DbSchema) o; if (!schema.getName().equals(getName())) { return false; } if (!annotations.equals(schema.getAnnotations())) { return false; } return Objects.equal(getFields(), schema.getFields()); } @Override public int hashCode() { return Objects.hashCode(name, annotations, fields); } @Override public String describe() { return "column family: " + name; } public boolean hasDuplicateField() { Set<String> uniqueFields = new HashSet<String>(); for (FieldInfo fieldInfo : this.fields) { if (uniqueFields.contains(fieldInfo.getName())) { return true; } else { uniqueFields.add(fieldInfo.getName()); } } return false; } public List<FieldInfo> getDuplicateFields() { Set<String> uniqueFields = new HashSet<String>(); List<FieldInfo> duplicateFields = new ArrayList<FieldInfo>(); for (FieldInfo fieldInfo : this.fields) { if (uniqueFields.contains(fieldInfo.getName())) { duplicateFields.add(fieldInfo); } else { uniqueFields.add(fieldInfo.getName()); } } return duplicateFields; } }