package org.apache.helix; /* * 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. */ import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.helix.api.config.NamespacedConfig; import org.apache.log4j.Logger; /** * A wrapper class for ZNRecord. Used as a base class for IdealState, CurrentState, etc. */ public class HelixProperty { private static Logger LOG = Logger.getLogger(HelixProperty.class); public enum HelixPropertyAttribute { BUCKET_SIZE, BATCH_MESSAGE_MODE } protected final ZNRecord _record; /** * Initialize the property with an identifier * @param id */ public HelixProperty(String id) { _record = new ZNRecord(id); } /** * Initialize the property with an existing ZNRecord * @param record */ public HelixProperty(ZNRecord record) { _record = new ZNRecord(record); } /** * Initialize the property by copying from another property * @param property */ public HelixProperty(HelixProperty property) { _record = new ZNRecord(property.getRecord()); } /** * Get the property identifier * @return the property id */ public final String getId() { return _record.getId(); } /** * Get the backing ZNRecord * @return ZNRecord object associated with this property */ public final ZNRecord getRecord() { return _record; } /** * Set the changes to the backing ZNRecord * @param deltaList list of ZNRecord updates to be made */ public final void setDeltaList(List<ZNRecordDelta> deltaList) { _record.setDeltaList(deltaList); } @Override public String toString() { return _record.toString(); } /** * Get the size of buckets defined * @return the bucket size, or 0 if not defined */ public int getBucketSize() { String bucketSizeStr = _record.getSimpleField(HelixPropertyAttribute.BUCKET_SIZE.toString()); int bucketSize = 0; if (bucketSizeStr != null) { try { bucketSize = Integer.parseInt(bucketSizeStr); } catch (NumberFormatException e) { // OK } } return bucketSize; } /** * Set the size of buckets defined * @param bucketSize the bucket size (will default to 0 if negative) */ public void setBucketSize(int bucketSize) { if (bucketSize <= 0) bucketSize = 0; _record.setSimpleField(HelixPropertyAttribute.BUCKET_SIZE.toString(), "" + bucketSize); } /** * static method that converts ZNRecord to an instance that subclasses HelixProperty * @param clazz subclass of HelixProperty * @param record the ZNRecord describing the property * @return typed instance corresponding to the record, or null if conversion fails */ public static <T extends HelixProperty> T convertToTypedInstance(Class<T> clazz, ZNRecord record) { if (record == null) { return null; } try { Constructor<T> constructor = clazz.getConstructor(new Class[] { ZNRecord.class }); return constructor.newInstance(record); } catch (Exception e) { LOG.error("Exception convert znrecord: " + record + " to class: " + clazz, e); } return null; } /** * Convert a collection of records to typed properties * @param clazz Subclass of HelixProperty * @param records the ZNRecords describing the property * @return list of typed instances for which the conversion succeeded, or null if records is null */ public static <T extends HelixProperty> List<T> convertToTypedList(Class<T> clazz, Collection<ZNRecord> records) { if (records == null) { return null; } List<T> decorators = new ArrayList<T>(); for (ZNRecord record : records) { T decorator = HelixProperty.convertToTypedInstance(clazz, record); if (decorator != null) { decorators.add(decorator); } } return decorators; } /** * Converts a list of records to a map of the record identifier to typed properties * @param records the ZNRecords to convert * @return id --> HelixProperty subclass map */ public static <T extends HelixProperty> Map<String, T> convertListToMap(List<T> records) { if (records == null) { return Collections.emptyMap(); } Map<String, T> decorators = new HashMap<String, T>(); for (T record : records) { decorators.put(record.getId(), record); } return decorators; } /** * Convert typed properties to a list of records * @param typedInstances objects subclassing HelixProperty * @return a list of ZNRecord objects */ public static <T extends HelixProperty> List<ZNRecord> convertToList(List<T> typedInstances) { if (typedInstances == null) { return Collections.emptyList(); } List<ZNRecord> records = new ArrayList<ZNRecord>(); for (T typedInstance : typedInstances) { records.add(typedInstance.getRecord()); } return records; } /** * Change the state of batch messaging * @param enable true to enable, false to disable */ public void setBatchMessageMode(boolean enable) { _record.setSimpleField(HelixPropertyAttribute.BATCH_MESSAGE_MODE.toString(), "" + enable); } /** * Get the state of batch messaging * @return true if enabled, false if disabled */ public boolean getBatchMessageMode() { String enableStr = _record.getSimpleField(HelixPropertyAttribute.BATCH_MESSAGE_MODE.toString()); if (enableStr == null) { return false; } try { return Boolean.parseBoolean(enableStr.toLowerCase()); } catch (Exception e) { return false; } } /** * Add namespaced configuration properties to this property * @param namespacedConfig namespaced properties */ public void addNamespacedConfig(NamespacedConfig namespacedConfig) { NamespacedConfig.addConfigToProperty(this, namespacedConfig); } /** * Get property validity * @return true if valid, false if invalid */ public boolean isValid() { return true; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj instanceof HelixProperty) { HelixProperty that = (HelixProperty) obj; if (that.getRecord() != null) { return that.getRecord().equals(this.getRecord()); } } return false; } }